راهنمای گام به گام ساخت یک وبلاگ با Flask

فهرست مطالب

“`html

راهنمای گام به گام ساخت یک وبلاگ با Flask

Flask یک فریم‌ورک میکروی پایتون است که برای توسعه برنامه‌های وب کوچک تا متوسط ​​بسیار مناسب است. سادگی، انعطاف‌پذیری و اکوسیستم غنی از افزونه‌ها، Flask را به یک انتخاب محبوب برای توسعه‌دهندگان، به‌ویژه کسانی که می‌خواهند کنترل بیشتری بر ساختار برنامه خود داشته باشند، تبدیل کرده است. در این راهنما، ما به طور گام به گام نحوه ساخت یک وبلاگ ساده با Flask را بررسی خواهیم کرد. این آموزش برای توسعه‌دهندگان با دانش پایه پایتون و HTML طراحی شده است.

پیش‌نیازها

قبل از شروع، مطمئن شوید که پیش‌نیازهای زیر را دارید:

  • پایتون 3.6 یا بالاتر
  • pip (مدیریت بسته پایتون)
  • دانش پایه HTML، CSS و JavaScript

برای بررسی نسخه پایتون خود، ترمینال یا command prompt خود را باز کنید و دستور زیر را اجرا کنید:

python --version

اگر پایتون را نصب ندارید، می‌توانید آن را از وب‌سایت رسمی پایتون (https://www.python.org/downloads/) دانلود و نصب کنید.

راه‌اندازی محیط توسعه

بهترین روش برای توسعه یک برنامه پایتون، استفاده از یک محیط مجازی است. این کار باعث می‌شود که وابستگی‌های پروژه شما جدا از سیستم عامل شما باقی بمانند و از تداخل بین پروژه‌ها جلوگیری شود.

برای ایجاد یک محیط مجازی، دستورات زیر را در ترمینال یا command prompt خود اجرا کنید:

mkdir flask_blog
 cd flask_blog
 python -m venv venv
 source venv/bin/activate  # برای Linux/macOS
 venv\Scripts\activate  # برای Windows
 

پس از فعال‌سازی محیط مجازی، می‌توانید Flask و سایر وابستگی‌های مورد نیاز را نصب کنید:

pip install flask flask-sqlalchemy flask-migrate flask-wtf wtforms

توضیح بسته‌های نصب شده:

  • Flask: فریم‌ورک اصلی وب.
  • Flask-SQLAlchemy: افزونه‌ای برای ادغام SQLAlchemy (ORM پایتون) با Flask.
  • Flask-Migrate: افزونه‌ای برای مدیریت مهاجرت‌های پایگاه داده.
  • Flask-WTF: افزونه‌ای برای مدیریت فرم‌ها.
  • WTForms: کتابخانه برای ایجاد فرم‌های وب.

ساختار پروژه

یک ساختار پروژه منظم به شما کمک می‌کند تا کد خود را سازماندهی کنید و نگهداری آن را آسان‌تر کنید. ساختار پیشنهادی ما به شرح زیر است:

flask_blog/
     ├── venv/         # محیط مجازی
     ├── app/          # کد برنامه
     │   ├── __init__.py
     │   ├── models.py   # مدل‌های پایگاه داده
     │   ├── forms.py    # فرم‌های وب
     │   ├── routes.py   # تعریف مسیرها و منطق برنامه
     │   ├── templates/  # فایل‌های HTML
     │   │   ├── base.html
     │   │   ├── index.html
     │   │   ├── post.html
     │   │   ├── new_post.html
     │   │   └── edit_post.html
     │   ├── static/   # فایل‌های CSS، JavaScript و تصاویر
     │   │   ├── style.css
     ├── migrations/   # فایل‌های مهاجرت پایگاه داده
     ├── config.py     # تنظیمات برنامه
     └── run.py        # فایل اصلی برای اجرای برنامه
 

فایل‌ها و پوشه‌های خالی با نام‌های بالا را ایجاد کنید.

پیکربندی برنامه

فایل config.py را ایجاد کنید و تنظیمات برنامه را در آن قرار دهید. این تنظیمات شامل کلید مخفی، URL پایگاه داده و سایر متغیرهای پیکربندی است.

محتوای فایل config.py:

import os

 class Config:
  SECRET_KEY = os.environ.get('SECRET_KEY') or 'your_secret_key'
  SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
  SQLALCHEMY_TRACK_MODIFICATIONS = False
 

توضیحات:

  • SECRET_KEY: یک کلید مخفی برای محافظت از برنامه در برابر حملات CSRF. بهتر است این مقدار را از محیط سیستم عامل بگیرید یا یک مقدار تصادفی قوی تولید کنید.
  • SQLALCHEMY_DATABASE_URI: URL پایگاه داده. در اینجا از SQLite به عنوان پایگاه داده استفاده می‌کنیم. شما می‌توانید از MySQL، PostgreSQL یا هر پایگاه داده دیگری که SQLAlchemy پشتیبانی می‌کند، استفاده کنید.
  • SQLALCHEMY_TRACK_MODIFICATIONS: تنظیم این گزینه به False باعث می‌شود که Flask-SQLAlchemy تغییرات را ردیابی نکند و از هشدارهای غیرضروری جلوگیری شود.

ایجاد برنامه Flask

فایل app/__init__.py را ایجاد کنید و برنامه Flask را در آن مقداردهی اولیه کنید:

from flask import Flask
 from flask_sqlalchemy import SQLAlchemy
 from flask_migrate import Migrate
 from flask_wtf.csrf import CSRFProtect
 from config import Config

 db = SQLAlchemy()
 migrate = Migrate()
 csrf = CSRFProtect()

 def create_app(config_class=Config):
  app = Flask(__name__)
  app.config.from_object(config_class)

  db.init_app(app)
  migrate.init_app(app, db)
  csrf.init_app(app)

  from app import models, routes

  return app
 

توضیحات:

  • در این فایل، ما Flask و افزونه‌های Flask-SQLAlchemy و Flask-Migrate را وارد می‌کنیم.
  • ما یک تابع به نام create_app تعریف می‌کنیم که یک instance از برنامه Flask را ایجاد و پیکربندی می‌کند.
  • app.config.from_object(config_class) تنظیمات برنامه را از کلاس Config که در فایل config.py تعریف کردیم، بارگیری می‌کند.
  • db.init_app(app) و migrate.init_app(app, db) افزونه‌های SQLAlchemy و Migrate را با برنامه Flask مرتبط می‌کنند.
  • from app import models, routes ماژول‌های models و routes را وارد می‌کنیم. این کار برای فعال‌سازی مدل‌های پایگاه داده و مسیرهای برنامه ضروری است.

تعریف مدل‌های پایگاه داده

فایل app/models.py را ایجاد کنید و مدل‌های پایگاه داده را در آن تعریف کنید. در این مثال، ما یک مدل برای پست‌های وبلاگ و یک مدل برای کاربران ایجاد می‌کنیم.

from datetime import datetime
 from app import db

 class User(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  username = db.Column(db.String(64), index=True, unique=True)
  email = db.Column(db.String(120), index=True, unique=True)
  password_hash = db.Column(db.String(128))
  posts = db.relationship('Post', backref='author', lazy='dynamic')

  def __repr__(self):
  return '<User {}>'.format(self.username)

 class Post(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  title = db.Column(db.String(140))
  body = db.Column(db.Text)
  timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
  user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

  def __repr__(self):
  return '<Post {}>'.format(self.title)
 

توضیحات:

  • مدل User دارای فیلدهای id، username، email، password_hash و posts است.
  • مدل Post دارای فیلدهای id، title، body، timestamp و user_id است.
  • db.relationship یک رابطه بین مدل‌های User و Post ایجاد می‌کند. backref='author' به ما امکان می‌دهد به نویسنده یک پست از طریق post.author دسترسی پیدا کنیم. lazy='dynamic' به ما امکان می‌دهد پرس و جوهای پیچیده‌تری را بر روی رابطه posts انجام دهیم.
  • db.ForeignKey('user.id') یک کلید خارجی به جدول user ایجاد می‌کند.

ایجاد مهاجرت پایگاه داده

پس از تعریف مدل‌های پایگاه داده، باید یک مهاجرت پایگاه داده ایجاد کنیم. این کار به ما امکان می‌دهد تغییرات را در پایگاه داده اعمال کنیم بدون اینکه داده‌ها را از دست بدهیم.

برای ایجاد یک مهاجرت پایگاه داده، دستورات زیر را در ترمینال یا command prompt خود اجرا کنید:

flask db init
 flask db migrate -m "Initial migration"
 flask db upgrade
 

توضیحات:

  • flask db init پوشه migrations را ایجاد می‌کند.
  • flask db migrate -m "Initial migration" یک فایل مهاجرت جدید ایجاد می‌کند که تغییرات را در مدل‌های پایگاه داده تعریف می‌کند.
  • flask db upgrade تغییرات را در پایگاه داده اعمال می‌کند.

تعریف فرم‌های وب

فایل app/forms.py را ایجاد کنید و فرم‌های وب را در آن تعریف کنید. در این مثال، ما یک فرم برای ایجاد و ویرایش پست‌ها و یک فرم برای ثبت نام کاربران ایجاد می‌کنیم.

from flask_wtf import FlaskForm
 from wtforms import StringField, TextAreaField, SubmitField, PasswordField
 from wtforms.validators import DataRequired, Length, Email, EqualTo

 class PostForm(FlaskForm):
  title = StringField('Title', validators=[DataRequired(), Length(min=1, max=140)])
  body = TextAreaField('Body', validators=[DataRequired()])
  submit = SubmitField('Submit')

 class RegistrationForm(FlaskForm):
  username = StringField('Username', validators=[DataRequired(), Length(min=2, max=64)])
  email = StringField('Email', validators=[DataRequired(), Email()])
  password = PasswordField('Password', validators=[DataRequired()])
  confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
  submit = SubmitField('Sign Up')

 class LoginForm(FlaskForm):
  username = StringField('Username', validators=[DataRequired()])
  password = PasswordField('Password', validators=[DataRequired()])
  submit = SubmitField('Login')
 

توضیحات:

  • مدل PostForm دارای فیلدهای title، body و submit است.
  • مدل RegistrationForm دارای فیلدهای username، email، password، confirm_password و submit است.
  • مدل LoginForm دارای فیلدهای username، password و submit است.
  • DataRequired، Length، Email و EqualTo اعتبارسنجی‌هایی هستند که برای اطمینان از اعتبار داده‌های وارد شده استفاده می‌شوند.

تعریف مسیرها و منطق برنامه

فایل app/routes.py را ایجاد کنید و مسیرها و منطق برنامه را در آن تعریف کنید. این فایل مسئول رسیدگی به درخواست‌های HTTP و ارائه پاسخ مناسب است.

from flask import render_template, flash, redirect, url_for, request
 from app import app, db
 from app.forms import PostForm, RegistrationForm, LoginForm
 from app.models import Post, User
 from flask_login import login_required, current_user, login_user, logout_user
 from werkzeug.security import generate_password_hash, check_password_hash
 from functools import wraps

 def admin_required(f):
  @wraps(f)
  def decorated_function(*args, **kwargs):
  if not current_user.is_authenticated or current_user.username != 'admin':
  flash('You do not have permission to access this page.', 'error')
  return redirect(url_for('index'))
  return f(*args, **kwargs)
  return decorated_function

 @app.route('/')
 def index():
  posts = Post.query.order_by(Post.timestamp.desc()).all()
  return render_template('index.html', posts=posts)

 @app.route('/post/')
 def post(post_id):
  post = Post.query.get_or_404(post_id)
  return render_template('post.html', post=post)

 @app.route('/new_post', methods=['GET', 'POST'])
 @login_required
 def new_post():
  form = PostForm()
  if form.validate_on_submit():
  post = Post(title=form.title.data, body=form.body.data, author=current_user)
  db.session.add(post)
  db.session.commit()
  flash('Your post has been created!', 'success')
  return redirect(url_for('index'))
  return render_template('new_post.html', form=form)

 @app.route('/edit_post/', methods=['GET', 'POST'])
 @login_required
 def edit_post(post_id):
  post = Post.query.get_or_404(post_id)
  if post.author != current_user and current_user.username != 'admin':
  flash('You do not have permission to edit this post.', 'error')
  return redirect(url_for('index'))
  form = PostForm(obj=post)
  if form.validate_on_submit():
  post.title = form.title.data
  post.body = form.body.data
  db.session.commit()
  flash('Your post has been updated!', 'success')
  return redirect(url_for('post', post_id=post.id))
  return render_template('edit_post.html', form=form, post=post)

 @app.route('/delete_post/')
 @login_required
 def delete_post(post_id):
  post = Post.query.get_or_404(post_id)
  if post.author != current_user and current_user.username != 'admin':
  flash('You do not have permission to delete this post.', 'error')
  return redirect(url_for('index'))
  db.session.delete(post)
  db.session.commit()
  flash('Your post has been deleted!', 'success')
  return redirect(url_for('index'))

 @app.route('/register', methods=['GET', 'POST'])
 def register():
  if current_user.is_authenticated:
  return redirect(url_for('index'))
  form = RegistrationForm()
  if form.validate_on_submit():
  hashed_password = generate_password_hash(form.password.data)
  user = User(username=form.username.data, email=form.email.data, password_hash=hashed_password)
  db.session.add(user)
  db.session.commit()
  flash('Your account has been created! You are now able to log in', 'success')
  return redirect(url_for('login'))
  return render_template('register.html', title='Register', form=form)

 @app.route('/login', methods=['GET', 'POST'])
 def login():
  if current_user.is_authenticated:
  return redirect(url_for('index'))
  form = LoginForm()
  if form.validate_on_submit():
  user = User.query.filter_by(username=form.username.data).first()
  if user and check_password_hash(user.password_hash, form.password.data):
  login_user(user)
  next_page = request.args.get('next')
  return redirect(next_page) if next_page else redirect(url_for('index'))
  else:
  flash('Login Unsuccessful. Please check username and password', 'danger')
  return render_template('login.html', title='Login', form=form)

 @app.route('/logout')
 def logout():
  logout_user()
  return redirect(url_for('index'))

 

توضیحات:

  • @app.route('/') یک دکوراتور است که مسیر / را به تابع index مرتبط می‌کند.
  • render_template('index.html', posts=posts) فایل index.html را با متغیر posts رندر می‌کند.
  • Post.query.order_by(Post.timestamp.desc()).all() تمام پست‌ها را از پایگاه داده واکشی می‌کند و آنها را بر اساس زمان ایجاد مرتب می‌کند.
  • flash('Your post has been created!', 'success') یک پیام فلش ایجاد می‌کند که در صفحه بعدی نمایش داده می‌شود.
  • redirect(url_for('index')) کاربر را به مسیر / هدایت می‌کند.
  • @login_required یک دکوراتور است که برای دسترسی به مسیر /new_post نیاز به ورود به سیستم دارد.
  • current_user یک متغیر است که کاربر فعلی را نشان می‌دهد.
  • generate_password_hash و check_password_hash توابعی هستند که برای هش کردن و بررسی رمز عبور استفاده می‌شوند.

ایجاد فایل‌های HTML

فایل‌های HTML را در پوشه app/templates ایجاد کنید. این فایل‌ها مسئول ارائه رابط کاربری برنامه هستند.

محتوای فایل app/templates/base.html:

<!DOCTYPE html>
 <html>
 <head>
  <title>{% block title %}{% endblock %}</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
 </head>
 <body>
  <nav>
  <ul>
  <li><a href="{{ url_for('index') }}">Home</a></li>
  {% if current_user.is_authenticated %}
  <li><a href="{{ url_for('new_post') }}">New Post</a></li>
  <li><a href="{{ url_for('logout') }}">Logout</a></li>
  {% else %}
  <li><a href="{{ url_for('login') }}">Login</a></li>
  <li><a href="{{ url_for('register') }}">Register</a></li>
  {% endif %}
  </ul>
  </nav>
  <div class="container">
  {% with messages = get_flashed_messages(with_categories=true) %}
  {% if messages %}
  <ul class="flashes">
  {% for category, message in messages %}
  <li class="{{ category }}">{{ message }}</li>
  {% endfor %}
  </ul>
  {% endif %}
  {% endwith %}
  {% block content %}{% endblock %}
  </div>
 </body>
 </html>
 

محتوای فایل app/templates/index.html:

{% extends "base.html" %}

 {% block title %}Home{% endblock %}

 {% block content %}
 <h1>Posts</h1>
 {% for post in posts %}
  <article>
  <h2><a href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2>
  <p>By {{ post.author.username }} on {{ post.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</p>
  <p>{{ post.body }}</p>
  {% if current_user.is_authenticated and (current_user == post.author or current_user.username == 'admin') %}
  <a href="{{ url_for('edit_post', post_id=post.id) }}">Edit</a>
  <a href="{{ url_for('delete_post', post_id=post.id) }}">Delete</a>
  {% endif %}
  </article>
 {% endfor %}
 {% endblock %}
 

محتوای فایل app/templates/post.html:

{% extends "base.html" %}

 {% block title %}{{ post.title }}{% endblock %}

 {% block content %}
 <article>
  <h1>{{ post.title }}</h1>
  <p>By {{ post.author.username }} on {{ post.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</p>
  <p>{{ post.body }}</p>
  {% if current_user.is_authenticated and (current_user == post.author or current_user.username == 'admin') %}
  <a href="{{ url_for('edit_post', post_id=post.id) }}">Edit</a>
  <a href="{{ url_for('delete_post', post_id=post.id) }}">Delete</a>
  {% endif %}
 </article>
 {% endblock %}
 

محتوای فایل app/templates/new_post.html:

{% extends "base.html" %}

 {% block title %}New Post{% endblock %}

 {% block content %}
 <h1>New Post</h1>
 <form method="POST">
  {{ form.csrf_token }}
  <div>
  {{ form.title.label }}<br>
  {{ form.title(size=32) }}
  {% if form.title.errors %}
  <ul class="errors">
  {% for error in form.title.errors %}
  <li>{{ error }}</li>
  {% endfor %}
  </ul>
  {% endif %}
  </div>
  <div>
  {{ form.body.label }}<br>
  {{ form.body(rows=10, cols=50) }}
  {% if form.body.errors %}
  <ul class="errors">
  {% for error in form.body.errors %}
  <li>{{ error }}</li>
  {% endfor %}
  </ul>
  {% endif %}
  </div>
  <div>
  {{ form.submit }}
  </div>
 </form>
 {% endblock %}
 

محتوای فایل app/templates/edit_post.html:

{% extends "base.html" %}

 {% block title %}Edit Post{% endblock %}

 {% block content %}
 <h1>Edit Post</h1>
 <form method="POST">
  {{ form.csrf_token }}
  <div>
  {{ form.title.label }}<br>
  {{ form.title(size=32) }}
  {% if form.title.errors %}
  <ul class="errors">
  {% for error in form.title.errors %}
  <li>{{ error }}</li>
  {% endfor %}
  </ul>
  {% endif %}
  </div>
  <div>
  {{ form.body.label }}<br>
  {{ form.body(rows=10, cols=50) }}
  {% if form.body.errors %}
  <ul class="errors">
  {% for error in form.body.errors %}
  <li>{{ error }}</li>
  {% endfor %}
  </ul>
  {% endif %}
  </div>
  <div>
  {{ form.submit }}
  </div>
 </form>
 {% endblock %}
 

محتوای فایل app/templates/register.html:

{% extends "base.html" %}
 {% block title %}Register{% endblock %}
 {% block content %}
 <div class="content-section">
  <form method="POST" action="">
  {{ form.hidden_tag() }}
  <fieldset class="form-group">
  <legend class="border-bottom mb-4">Join Today</legend>
  <div class="form-group">
  {{ form.username.label(class="form-control-label") }}
  {% if form.username.errors %}
  {{ form.username(class="form-control form-control-lg is-invalid") }}
  <div class="invalid-feedback">
  {% for error in form.username.errors %}
  <span>{{ error }}</span>
  {% endfor %}
  </div>
  {% else %}
  {{ form.username(class="form-control form-control-lg") }}
  {% endif %}
  </div>
  <div class="form-group">
  {{ form.email.label(class="form-control-label") }}
  {% if form.email.errors %}
  {{ form.email(class="form-control form-control-lg is-invalid") }}
  <div class="invalid-feedback">
  {% for error in form.email.errors %}
  <span>{{ error }}</span>
  {% endfor %}
  </div>
  {% else %}
  {{ form.email(class="form-control form-control-lg") }}
  {% endif %}
  </div>
  <div class="form-group">
  {{ form.password.label(class="form-control-label") }}
  {% if form.password.errors %}
  {{ form.password(class="form-control form-control-lg is-invalid") }}
  <div class="invalid-feedback">
  {% for error in form.password.errors %}
  <span>{{ error }}</span>
  {% endfor %}
  </div>
  {% else %}
  {{ form.password(class="form-control form-control-lg") }}
  {% endif %}
  </div>
  <div class="form-group">
  {{ form.confirm_password.label(class="form-control-label") }}
  {% if form.confirm_password.errors %}
  {{ form.confirm_password(class="form-control form-control-lg is-invalid") }}
  <div class="invalid-feedback">
  {% for error in form.confirm_password.errors %}
  <span>{{ error }}</span>
  {% endfor %}
  </div>
  {% else %}
  {{ form.confirm_password(class="form-control form-control-lg") }}
  {% endif %}
  </div>
  </fieldset>
  <div class="form-group">
  {{ form.submit(class="btn btn-outline-info") }}
  </div>
  <div class="border-top pt-3">
  <small class="text-muted">
  Already Have An Account? <a class="ml-2" href="{{ url_for('login') }}">Sign In</a>
  </small>
  </div>
  </form>
 </div>
 {% endblock content %}
 

محتوای فایل app/templates/login.html:

{% extends "base.html" %}
 {% block title %}Login{% endblock %}
 {% block content %}
 <div class="content-section">
  <form method="POST" action="">
  {{ form.hidden_tag() }}
  <fieldset class="form-group">
  <legend class="border-bottom mb-4">Log In</legend>
  <div class="form-group">
  {{ form.username.label(class="form-control-label") }}
  {{ form.username(class="form-control form-control-lg") }}
  </div>
  <div class="form-group">
  {{ form.password.label(class="form-control-label") }}
  {{ form.password(class="form-control form-control-lg") }}
  </div>
  </fieldset>
  <div class="form-group">
  {{ form.submit(class="btn btn-outline-info") }}
  </div>
  </form>
 </div>
 {% endblock content %}
 

توضیحات:

  • {% extends "base.html" %} فایل base.html را به عنوان پایه برای این فایل HTML تعریف می‌کند.
  • {% block title %}{% endblock %} یک بلوک است که می‌تواند در فایل‌های HTML فرزند مقداردهی شود.
  • {{ url_for('index') }} URL مربوط به مسیر index را تولید می‌کند.
  • {{ post.title }} مقدار فیلد title از متغیر post را نمایش می‌دهد.
  • {{ form.title.label }} برچسب مربوط به فیلد title از فرم form را نمایش می‌دهد.
  • {{ form.title(size=32) }} فیلد title از فرم form را با اندازه 32 نمایش می‌دهد.
  • {{ form.title.errors }} خطا‌های مربوط به فیلد title از فرم form را نمایش می‌دهد.

ایجاد فایل CSS

فایل app/static/style.css را ایجاد کنید و استایل‌های CSS را در آن قرار دهید. این فایل مسئول ظاهر برنامه است.

یک مثال ساده از محتوای فایل app/static/style.css:

body {
  font-family: sans-serif;
  margin: 0;
  padding: 0;
 }

 nav {
  background-color: #333;
  color: white;
  padding: 10px;
 }

 nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
 }

 nav li {
  float: left;
 }

 nav li a {
  display: block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
 }

 nav li a:hover {
  background-color: #ddd;
  color: black;
 }

 .container {
  margin: 20px;
 }

 article {
  margin-bottom: 20px;
  padding: 10px;
  border: 1px solid #ddd;
 }

 .flashes {
  list-style: none;
  padding: 0;
  margin-bottom: 20px;
 }

 .flashes li {
  padding: 10px;
  margin-bottom: 5px;
  border-radius: 5px;
 }

 .flashes li.success {
  background-color: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
 }

 .flashes li.error {
  background-color: #f8d7da;
  color: #721c24;
  border: 1px solid #f5c6cb;
 }
 

اجرای برنامه

فایل run.py را ایجاد کنید و برنامه Flask را در آن اجرا کنید.

محتوای فایل run.py:

from app import create_app

 app = create_app()

 if __name__ == '__main__':
  app.run(debug=True)
 

توضیحات:

  • from app import create_app تابع create_app را از ماژول app وارد می‌کند.
  • app = create_app() یک instance از برنامه Flask ایجاد می‌کند.
  • app.run(debug=True) برنامه Flask را در حالت debug اجرا می‌کند.

برای اجرای برنامه، دستور زیر را در ترمینال یا command prompt خود اجرا کنید:

python run.py
 

برنامه شما اکنون باید در آدرس http://127.0.0.1:5000/ در دسترس باشد.

امنیت

هنگام ساخت یک وبلاگ

“تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”

قیمت اصلی 2.290.000 ریال بود.قیمت فعلی 1.590.000 ریال است.

"تسلط به برنامه‌نویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"

"با شرکت در این دوره جامع و کاربردی، به راحتی مهارت‌های برنامه‌نویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر می‌سازد تا به سرعت الگوریتم‌های پیچیده را درک کرده و اپلیکیشن‌های هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفه‌ای و امکان دانلود و تماشای آنلاین."

ویژگی‌های کلیدی:

بدون نیاز به تجربه قبلی برنامه‌نویسی

زیرنویس فارسی با ترجمه حرفه‌ای

۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان