شروع سریع

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

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

یک برنامه ساده فلاسک، چیزی شبیه به این است:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

این کد چه کاری می‌کند؟

  1. ابتدا کلاس Flask را وارد کردیم. یک نمونه کلاس در برنامه WSGI ما اینگونه خواهد بود.

  2. بعد، یک نمونه از این کلاس ایجاد می کنیم. اولین آرگومان نام ماژول یا بسته برنامه است. __name__ میانبر مناسبی برای این کار است و در اکثر موارد مناسب است. این آرگومان اجباری است چون باید فلاسک بداند که کجا به دنبال منابعی مانند قالب ها و فایل های استاتیک باشد.

  3. سپس از دکوراتور route() استفاده می کنیم تا به فلاسک بگوییم چه URL ی باید عملکرد ما را راه اندازی کند.

  4. تابع پیامی را که می خواهیم در مرورگر کاربر نمایش دهیم برمی گرداند. نوع محتوای پیش فرض HTML است، بنابراین کد HTML در رشته، توسط مرورگر ارائه می شود.

آن را به صورت hello.py یا هر چیز مشابه دیگر ذخیره کنید. مطمئن شوید که برنامه خود را flask.py نام گذاری نکنید زیرا با خود فلاسک در تضاد است.

To run the application, use the flask command or python -m flask. You need to tell the Flask where your application is with the --app option.

$ flask --app hello run
 * Serving Flask app 'hello'
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

رفتار کشف برنامه

As a shortcut, if the file is named app.py or wsgi.py, you don't have to use --app. See Command Line Interface for more details.

این یک سرور داخلی بسیار ساده را راه اندازی می کند که برای آزمایش به اندازه کافی خوب است اما احتمالاً آن چیزی نیست که می خواهید در تولید استفاده کنید. برای گزینه های استقرار به Deploying to Production مراجعه کنید.

اکنون به http://127.0.0.1:5000/ بروید، و باید سلام جهان را ببینید.

اگر برنامه دیگری در حال حاضر از پورت 5000 استفاده می کند، زمانی که سرور تلاش می کند راه اندازی شود، OSError: [WinError 10013] یا OSError: [Errno 98] را مشاهده خواهید کرد. برای نحوه رسیدگی به آن به آدرس در حال استفاده مراجعه کنید.

سرور قابل مشاهده خارجی

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

اگر دیباگر را غیرفعال کرده اید یا به کاربران شبکه خود اعتماد دارید، می توانید سرور را به سادگی با افزودن --host=0.0.0.0 به خط فرمان در دسترس عموم قرار دهید:

$ flask run --host=0.0.0.0

این به سیستم عامل شما می گوید که به تمام IP های عمومی گوش دهد.

حالت اشکال زدایی

دستور flask run میتواند کار های بیشتری از توسعه سرور انجام دهد. با فعال سازی حالت اشکال زدایی سرور درصورت تغییر کد به صورت خودکار باز راه‌اندازی میشود و در صورت بروز خطا در هنگام درخواست، یک دیباگر تعاملی را در مرورگر نشان می دهد.

The interactive debugger in action.

هشدار

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

To enable debug mode, use the --debug option.

$ flask --app hello run --debug
 * Serving Flask app 'hello'
 * Debug mode: on
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: nnn-nnn-nnn

همچنین ببینید:

فرار HTML (HTML Escaping)

هنگام برگرداندن HTML (نوع پاسخ پیش‌فرض در فلاسک)، هر مقدار ارائه‌شده توسط کاربر که در خروجی ارائه می‌شود، باید برای محافظت در برابر حملات XSS مقاوم باشند. قالب‌های HTML ارائه‌شده با Jinja، که بعداً معرفی شدند، این کار را به‌طور خودکار انجام می‌دهند.

تابع escape()، که در اینجا نشان داده شده است، می تواند به صورت دستی استفاده شود. در بیشتر نمونه ها برای اختصار از آن حذف شده است، اما همیشه باید از نحوه استفاده از داده های نامعتبر آگاه باشید.

from markupsafe import escape

@app.route("/<name>")
def hello(name):
    return f"Hello, {escape(name)}!"

اگر کاربر موفق به ارسال <script>alert("bad")</script> شود، فرار باعث می شود که به جای اجرای اسکریپت در مرورگر کاربر، به صورت متن ارائه شود.

<name> در مسیر یک مقدار از URL گرفته و به تابع view ارسال می کند. این قوانین متغیر در زیر توضیح داده شده است.

مسیریابی

برنامه های وب مدرن از URL های معنی دار برای کمک به کاربران استفاده می کنند. اگر کاربران یک صفحه را دوست داشته باشند و اگر صفحه از URL معنی‌داری استفاده کند، کاربران می‌توانند URL را به خاطر بسپارند و مستقیماً از صفحه بازدید کنند.

از دکوراتور route() برای اتصال یک تابع به URL استفاده کنید.

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello, World'

شما میتوانید کار های زیادی را انجام دهید! میتوانید بخشی از URL را پویا کنید و چند قانون به تابع اضافه کنید.

قوانین متغیر

می‌توانید با علامت‌گذاری بخش‌ها با <variable_name> ، بخش‌هایی از متغیر را به URL اضافه کنید. سپس تابع شما <variable_name> را به عنوان آرگومان کلمه کلیدی دریافت می کند. به صورت اختیاری، می توانید از یک مبدل برای تعیین نوع آرگومان مانند <converter:variable_name> استفاده کنید.

from markupsafe import escape

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return f'User {escape(username)}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return f'Post {post_id}'

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    # show the subpath after /path/
    return f'Subpath {escape(subpath)}'

انواع مبدل:

رشته

به صورت پیشفرض هر متنی را بدون اسلش می پذیرد

عدد صحیح

اعداد صحیح مثبت را می پذیرد

عدد اعشاری

تمام اعداد اعشاری مثبت را می پذیرد

مسیر

مانند رشته است ولی اسلش را هم می پذیرد

uuid

رشته های UUID را می پذیرد

URL های منحصر به فرد / رفتار تغییر مسیر

دو قانون زیر در استفاده از اسلش انتهایی متفاوت است.

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

URL متعارف برای نقطه پایانی projects دارای یک اسلش انتهایی است. این شبیه به یک پوشه در یک سیستم فایل است. اگر بدون اسلش انتهایی (/projects) به URL دسترسی داشته باشید، Flask شما را به URL متعارف با اسلش انتهایی (/projects/) هدایت می کند.

URL متعارف برای نقطه پایانی about دارای یک اسلش انتهایی نیست. این شبیه به نام مسیر یک فایل است. دسترسی به URL با اسلش انتهایی (/about/) باعث ایجاد خطای ۴۰۴ «یافت نشد» می شود. این کمک می کند تا URL ها برای این منابع منحصر به فرد باقی بمانند، که به موتورهای جستجو کمک می کند تا از نمایه سازی یک صفحه دو بار جلوگیری کنند.

ساخت URL

برای ساخت یک URL برای یک تابع خاص، از تابع url_for() استفاده کنید. نام تابع را به عنوان اولین آرگومان و هر تعداد آرگومان کلمه کلیدی که هر کدام مربوط به بخش متغیری از قانون URL است را می پذیرد. قسمت های متغیر ناشناخته به عنوان پارامترهای پرس و جو به URL اضافه می شوند.

چرا می خواهید URL ها را با استفاده از تابع url_for() بسازید به جای آنکه کد ها را در قالب های خود بنویسید؟

  1. معکوس کردن اغلب توصیفی از کدگذاری سخت URL ها است.

  2. می‌توانید به‌جای اینکه به یاد داشته باشید که URL‌های کدگذاری‌شده را به‌صورت دستی تغییر دهید، آدرس‌های اینترنتی خود را یکباره تغییر دهید.

  3. ساختمان فرار URL از کاراکترهای خاص را به طور شفاف کنترل می کند.

  4. مسیرهای تولید شده همیشه مطلق هستند و از رفتار غیرمنتظره مسیرهای وابسته در مرورگرها جلوگیری می کنند.

  5. اگر برنامه شما خارج از ریشه URL قرار داده شده است، به عنوان مثال، به جای / در /myapplication باشد، url_for() به درستی آن را برای شما مدیریت می کند.

به عنوان مثال، در اینجا از روش test_request_context() برای امتحان کردن url_for() استفاده می کنیم. test_request_context() به فلاسک می گوید که به گونه ای رفتار کند که انگار در حال رسیدگی به یک درخواست است حتی زمانی که ما از پوسته پایتون استفاده می کنیم. به متن محلی مراجعه کنید.

from flask import url_for

@app.route('/')
def index():
    return 'index'

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return f'{username}\'s profile'

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))
/
/login
/login?next=/
/user/John%20Doe

متود های HTTP

برنامه های کاربردی وب هنگام دسترسی به URL ها از روش های مختلف HTTP استفاده می کنند. هنگام کار با فلاسک باید با روش های HTTP آشنا شوید. به طور پیش‌فرض، یک مسیر فقط به درخواست‌های GET پاسخ می‌دهد. می‌توانید از آرگومان``methods`` دکوراتور route() برای مدیریت روش‌های مختلف HTTP استفاده کنید.

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return do_the_login()
    else:
        return show_the_login_form()

The example above keeps all methods for the route within one function, which can be useful if each part uses some common data.

You can also separate views for different methods into different functions. Flask provides a shortcut for decorating such routes with get(), post(), etc. for each common HTTP method.

@app.get('/login')
def login_get():
    return show_the_login_form()

@app.post('/login')
def login_post():
    return do_the_login()

اگر GET وجود داشته باشد، فلاسک به طور خودکار از روش HEAD پشتیبانی می‌کند و درخواست‌های «HEAD» را مطابق با HTTP RFC مدیریت می‌کند. به همین ترتیب، OPTIONS به طور خودکار برای شما پیاده سازی می شود.

فایل های استاتیک

برنامه های وب پویا به فایل های استاتیک نیز نیاز دارند. معمولاً فایل های CSS و جاوا اسکریپت از آنجا می آیند. در حالت ایده آل وب سرور شما به گونه ای پیکربندی شده است که آنها را برای شما ارائه دهد، اما در حین توسعه، فلاسک می تواند این کار را نیز انجام داد. فقط یک پوشه به نام static در پکیج خود یا در کنار ماژول خود ایجاد کنید و در آدرس /static در برنامه در دسترس خواهد بود.

برای ایجاد URL برای فایل‌های استاتیک، از نام نقطه پایانی ویژه 'static' استفاده کنید:

url_for('static', filename='style.css')

فایل باید در سیستم فایل به صورت static/style.css ذخیره شود.

الگوهای رندرینگ

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

Templates can be used to generate any type of text file. For web applications, you'll primarily be generating HTML pages, but you can also generate markdown, plain text for emails, and anything else.

For a reference to HTML, CSS, and other web APIs, use the MDN Web Docs.

برای رندر یک الگو می توانید از روش render_template() استفاده کنید. تنها کاری که باید انجام دهید این است که نام قالب و متغیرهایی را که می خواهید به عنوان آرگومان های کلمه کلیدی به موتور قالب منتقل کنید، ارائه دهید. در اینجا یک مثال ساده از نحوه ارائه یک الگو آورده شده است:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

فلاسک دارای مقادیر زیادی از پیکربندی با پیش فرض های معقول، و چند قرارداد در هنگام شروع است. طبق قرارداد، قالب‌ها و فایل‌های استاتیک در زیرشاخه‌های منبع برنامه، با نام‌ های templates و static ذخیره می‌شوند. البته میتوان آنها را تغییر داد ولی معمولا به خصوص در هنگام شروع مجبور نیستید که آنها را تغییر دهید:

مورد ۱: یک ماژول:

/application.py
/templates
    /hello.html

مورد ۲: یک ماژول:

/application
    /__init__.py
    /templates
        /hello.html

برای قالب ها می توانید از قدرت کامل قالب های Jinja2 استفاده کنید. برای اطلاعات بیشتر به مستندات الگوی jinja2 مراجعه کنید.

اینجا یک مثال برای قالب است:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

در داخل الگوها همچنین به config, request, session و g [1] و همچنین به توابع url_for() و get_flashed_messages() دسترسی دارید.

اگر از وراثت استفاده میکنید.، الگوها بسیار مفید هستند. اگر می خواهید بدانید که چگونه کار می کند، به Template Inheritance مراجعه کنید. اساساً، وراثت قالب، نگه داشتن عناصر خاصی را در هر صفحه (مانند هدر، ناوبری و پاورقی) ممکن می‌سازد.

فرار خودکار فعال است، بنابراین اگر name حاوی HTML باشد، به طور خودکار از آن خنثی میکند. اگر می‌توانید به متغیری اعتماد کنید و می‌دانید که HTML ایمن خواهد بود (مثلاً چون از ماژولی است که نشانه‌گذاری ویکی را به HTML تبدیل می‌کند)، می‌توانید با استفاده از کلاس Markup آن را به عنوان امن علامت‌گذاری کنید. یا با استفاده از فیلتر |safe در الگو اینکار را انجام دهید. برای نمونه های بیشتر به مستندات Jinja 2 بروید.

در اینجا یک مقدمه اولیه برای نحوه عملکرد کلاس Markup آورده شده است:

>>> from markupsafe import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup('<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup('&lt;blink&gt;hacker&lt;/blink&gt;')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
'Marked up » HTML'
Changelog

تغییر داده شده در نسخه 0.5: فرار خودکار دیگر برای همه الگوها فعال نیست. فرار خودکار برای پسوند های زیر انجام میشود: : .html, .htm, .xml, .xhtml. الگوهای بارگذاری شده از یک رشته، فرار خودکار را غیر فعال خواهد کرد.

دسترسی به داده های درخواستی

برای برنامه های کاربردی وب، بسیار مهم است که به داده هایی که مشتری به سرور ارسال می کند واکنش نشان دهد. در فلاسک این اطلاعات توسط شیء سراسری request ارائه می شود. اگر تجربه‌ای با پایتون دارید، ممکن است تعجب کنید که چگونه آن شی می‌تواند سراسری باشد و چگونه فلاسک می‌تواند همچنان امن باشد. پاسخ متن محلی است:

متن محلی

اطلاعات داخلی

اگر می‌خواهید بدانید که چگونه کار می‌کند و چگونه می‌توانید آزمایش‌ها را با متن محلی پیاده‌سازی کنید، این بخش را بخوانید، در غیر این صورت فقط آن را نادیده بگیرید.

برخی از اشیاء در فلاسک، اشیاء جهانی هستند، اما از نوع معمول نیستند. این اشیاء پروکسی برای اشیایی هستند که محلی برای یک زمینه خاص هستند. اما درک آن بسیار آسان است.

تصور کنید که زمینه، موضوع مدیریت است. یک درخواست وارد می‌شود و وب‌سرور تصمیم می‌گیرد یک رشته جدید ایجاد کند (یا چیز دیگری، شی زیربنایی قادر است با سیستم‌ های همزمانی غیر از رشته‌ها سروکار داشته باشد). هنگامی که فلاسک رسیدگی به درخواست داخلی خود را شروع می کند، متوجه می شود که رشته فعلی زمینه فعال است و برنامه فعلی و محیط های WSGI را به آن زمینه (رشته) متصل می کند. این کار را به روشی هوشمند انجام می دهد تا یک برنامه بتواند برنامه دیگری را بدون شکستن فراخوانی کند.

پس این برای شما چه معنی دارد؟ اساساً می توانید کاملاً نادیده بگیرید که این مورد است مگر اینکه در حال انجام کاری مانند تست واحد باشید. متوجه خواهید شد که کدی که به یک شی درخواست بستگی دارد ناگهان شکسته می شود زیرا شی درخواستی وجود ندارد. راه حل این است که خودتان یک شی درخواست ایجاد کنید و آن را به متن متصل کنید. ساده ترین راه حل برای تست واحد استفاده از مدیر زمینه test_request_context() است. در ترکیب با عبارت with یک درخواست آزمایشی را متصل می کند تا بتوانید با آن تعامل داشته باشید. به عنوان مثال:

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

امکان دیگر ارسال یک محیط WSGI کامل به متد request_context() method:

with app.request_context(environ):
    assert request.method == 'POST'

شی درخواست

شی درخواست در بخش API مستند شده است و ما در اینجا آن را با جزئیات پوشش نمی دهیم (به Request مراجعه کنید). در اینجا یک مرور کلی از برخی از رایج ترین عملیات ارائه شده است. اول از همه، شما باید آن را از ماژول flask وارد کنید:

from flask import request

روش درخواست فعلی با استفاده از ویژگی method در دسترس است. برای دسترسی به داده‌های فرم (داده‌های ارسال شده در درخواست POST یا PUT) می‌توانید از ویژگی form استفاده کنید. در اینجا یک مثال کامل از دو ویژگی ذکر شده در بالا آورده شده است:

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

اگر کلید در ویژگی form وجود نداشته باشد چه اتفاقی می افتد؟ در آن صورت، یک KeyError ویژه ایجاد می شود. می‌توانید آن را مانند یک KeyError استاندارد دریافت کنید، اما اگر این کار را نکنید، یک صفحه خطای درخواست بد HTTP 400 نشان داده می‌شود. بنابراین برای بسیاری از موقعیت ها، لازم نیست با آن مشکل کنار بیایید.

برای دسترسی به پارامترهای ارسال شده در URL (?key=value) می توانید از ویژگی args استفاده کنید:

searchword = request.args.get('key', '')

توصیه می‌کنیم با get یا با KeyError به پارامترهای URL دسترسی پیدا کنید، زیرا کاربر ممکن است URL را تغییر دهند و در این صورت یک صفحه درخواست 400 بد برای آن‌ها ارائه می دهد که کاربر پسند نیست.

برای فهرست کاملی از متدها و ویژگی های شی درخواست، مستندات Request را بررسی کنید.

آپلود فایل

شما میتوانید به آسانی فایل هایتان را با فلاسک هندل کنید. فقط نباید فراموش کنید که enctype="multipart/form-data" را در فرم HTML خودتان قرار دهید مرورگر شما بدون این فایلی را انتقال نخواهد داد.

فایل های آپلود شده در حافظه یا یک مکان موقت در فایل سیستم ها ذخیره می‌شوند. شما میتوانید با نگاه کردن به شی files دسترسی مناسب برای این درخواست را بدهید. هر فایل آپلود شده در دایرکتوری ای ذخیره می‌شود. این مانند شی استاندارد file رفتار می‌کند ولی شیوه save() همیشه مجاز می‌کند تا شما این فایل را در فایل سیستم ها ذخیره کنید:

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

اگر شما میخواهید بدانید که چگونه فایل ها قبل از آپلود در کلاینت برنامه شما نام گزاری می‌شوند شیوه filename را بررسی کنید. با این حال لطفاً به خاطر داشته باشید که این شیوه قابل جعل است، بنابراین هرگز به آن ارزش اعتماد نکنید. اگر می خواهید از نام فایل کلاینت برای ذخیره فایل در سرور استفاده کنید، آن را از طریق تابع secure_filename() که Werkzeug برای شما ارائه می کند، ارسال کنید:

from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['the_file']
        file.save(f"/var/www/uploads/{secure_filename(file.filename)}")
    ...

برای مثال های بهتر Uploading Files را ببینید.

کوکی ها(Cookies)

برای دسترسی به کوکی ها می توانید از ویژگی cookies استفاده کنید. برای تنظیم کوکی ها می توانید از روش set_cookie برای اشیاء پاسخ استفاده کنید. ویژگی cookies از اشیاء درخواست، یک فرهنگ لغت با تمام کوکی هایی است که مشتری ارسال می کند. اگر می‌خواهید از جلسات استفاده کنید، مستقیماً از کوکی‌ها استفاده نکنید، بلکه از جلسات(Sessions) در Flask استفاده کنید که امنیت را در بالای کوکی‌ها برای شما اضافه می‌کند.

خواندن کوکی ها:

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

ذخیره کوکی ها:

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

توجه داشته باشید که کوکی ها روی اشیاء پاسخ(response objects) تنظیم می شوند. از آنجایی که شما معمولاً فقط رشته ها را از توابع view برمی گردانید، Flask آنها را به اشیاء پاسخ برای شما تبدیل می کند. اگر صراحتاً می خواهید این کار را انجام دهید، می توانید از تابع make_response() استفاده کنید و سپس آن را تغییر دهید.

گاهی اوقات ممکن است بخواهید یک کوکی را در نقطه ای تنظیم کنید که شی پاسخ هنوز وجود ندارد. این کار با استفاده از الگوی Deferred Request Callbacks امکان پذیر است.

برای این نیز به درباره پاسخ ها مراجعه کنید.

تغییر مسیرها و خطاها(Redirects and Errors)

برای تغییر مسیر کاربر به نقطه پایانی دیگر، از تابع redirect() استفاده کنید. برای لغو زودهنگام درخواست با کد خطا، از تابع abort() استفاده کنید:

from flask import abort, redirect, url_for

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

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

این یک مثال نسبتاً بی‌معنی است زیرا کاربر از فهرست به صفحه‌ای هدایت می‌شود که نمی‌تواند به آن دسترسی داشته باشد (۴۰۱ به معنای دسترسی ممنوع است) اما نشان می‌دهد که چگونه کار می‌کند.

به طور پیش فرض یک صفحه خطای سیاه و سفید برای هر کد خطا نشان داده می شود. اگر می‌خواهید صفحه خطا را سفارشی کنید، می‌توانید از دکوراتور errorhandler() استفاده کنید:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

بعد از فراخوانی render_template() به «۴۰۴» توجه کنید. این به فلاسک می گوید که کد وضعیت آن صفحه باید ۴۰۴ باشد که به معنای یافت نشد. به طور پیش فرض «۲۰۰» در نظر گرفته شده است که به این معنی است: همه چیز خوب پیش رفت.

برای جزئیات بیشتر به مدیریت خطا های برنامه مراجعه کنید.

درباره پاسخ ها

The return value from a view function is automatically converted into a response object for you. If the return value is a string it's converted into a response object with the string as response body, a 200 OK status code and a text/html mimetype. If the return value is a dict or list, jsonify() is called to produce a response. The logic that Flask applies to converting return values into response objects is as follows:

  1. اگر یک شی پاسخ از نوع صحیح برگردانده شود، مستقیماً از نمای بازگردانده می شود.

  2. اگر یک رشته باشد، یک شی پاسخ با آن داده و پارامترهای پیش فرض ایجاد می شود.

  3. If it's an iterator or generator returning strings or bytes, it is treated as a streaming response.

  4. If it's a dict or list, a response object is created using jsonify().

  5. اگر یک tuple برگردانده شود، آیتم های تاپل می توانند اطلاعات بیشتری را ارائه دهند. این تاپل ها باید به شکل (response, status)،(response, headers) یا (response, status, headers) باشند. مقدار status کد وضعیت را لغو می کند و headers می تواند فهرست یا فرهنگ لغت مقادیر اضافی سرصفحه باشد.

  6. اگر هیچ کدام از این موارد کار نکرد، فلاسک مقدار بازگشتی را یک برنامه معتبر WSGI فرض می‌کند و آن را به یک شی پاسخ تبدیل می‌کند.

اگر می خواهید شی پاسخ به دست آمده را در داخل view نگه دارید، می توانید از تابع make_response() استفاده کنید.

تصور کنید نماای مثل این دارید:

from flask import render_template

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

شما فقط باید عبارت return را با make_response() بگزارید و شی پاسخ را دریافت کنید تا آن را تغییر دهید، سپس آن را برگردانید:

from flask import make_response

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

ای پی آی با جیسان(APIs with JSON)

A common response format when writing an API is JSON. It's easy to get started writing such an API with Flask. If you return a dict or list from a view, it will be converted to a JSON response.

@app.route("/me")
def me_api():
    user = get_current_user()
    return {
        "username": user.username,
        "theme": user.theme,
        "image": url_for("user_image", filename=user.image),
    }

@app.route("/users")
def users_api():
    users = get_all_users()
    return [user.to_json() for user in users]

This is a shortcut to passing the data to the jsonify() function, which will serialize any supported JSON data type. That means that all the data in the dict or list must be JSON serializable.

For complex types such as database models, you'll want to use a serialization library to convert the data to valid JSON types first. There are many serialization libraries and Flask API extensions maintained by the community that support more complex applications.

جلسات(Sessions)

علاوه بر شی درخواست، شی دومی به نام session نیز وجود دارد که به شما امکان می دهد اطلاعات خاص یک کاربر را از یک درخواست به درخواست دیگر ذخیره کنید. این در بالای کوکی ها برای شما اجرا می شود و کوکی ها را به صورت رمزنگاری امضا می کند. این بدان معناست که کاربر می تواند به محتویات کوکی شما نگاه کند اما آن را تغییر ندهد، مگر اینکه کلید مخفی مورد استفاده برای امضا را بداند.

برای استفاده از جلسات باید یک کلید مخفی تنظیم کنید. نحوه کار جلسات به شرح زیر است:

from flask import session

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return f'Logged in as {session["username"]}'
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

چگونه کلید مخفی خوبی بسازیم

یک کلید مخفی باید تا حد امکان تصادفی باشد. سیستم عامل شما راه هایی برای تولید داده های بسیار تصادفی بر اساس یک ژنراتور تصادفی رمزنگاری دارد. از دستور زیر برای ایجاد سریع مقدار برای Flask.secret_key (یا SECRET_KEY):

$ python -c 'import secrets; print(secrets.token_hex())'
'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

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

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

فلش کردن پیام(Message Flashing)

برنامه ها و رابط های کاربری خوب همه در مورد بازخورد هستند. اگر کاربر بازخورد کافی دریافت نکند، احتمالاً از برنامه متنفر خواهد شد. فلاسک یک راه بسیار ساده برای ارائه بازخورد به کاربر با سیستم فلش ارائه می دهد. سیستم فلش اساساً امکان ضبط یک پیام در انتهای درخواست و دسترسی به آن در درخواست بعدی (و فقط درخواست بعدی) را فراهم می کند. این معمولاً با یک الگوی طرح بندی ترکیب می شود تا پیام را آشکار کند.

برای فلش کردن یک پیام از روش flash() استفاده کنید، برای دریافت پیام ها می توانید از get_flashed_messages() استفاده کنید که در قالب ها نیز موجود است. برای مثال کامل به Message Flashing مراجعه کنید.

لاگ کردن(Logging)

Changelog

جدید در نسخه 0.3.

گاهی اوقات ممکن است در موقعیتی قرار بگیرید که با داده هایی برخورد می کنید که باید درست باشند، اما در واقع اینطور نیست. به عنوان مثال، ممکن است تعدادی کد سمت کلاینت داشته باشید که یک درخواست HTTP را به سرور ارسال می کند، اما به وضوح بدشکل است. این ممکن است به دلیل دستکاری کاربر در داده ها یا خرابی کد مشتری باشد. در بیشتر مواقع پاسخ دادن با 400 Bad Request در آن موقعیت اشکالی ندارد، اما گاهی اوقات این کار انجام نمی‌شود و کد باید به کار خود ادامه دهد.

ممکن است هنوز بخواهید ثبت کنید که یک اتفاق عجیب رخ داده است. اینجاست که لاگرها به کار می آیند. از Flask 0.3 یک لاگر از قبل برای استفاده شما پیکربندی شده است.

در اینجا چند نمونه از لاگ ها آورده شده است:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

logger پیوست شده یک گزارش استاندارد Logger است، بنابراین برای اطلاعات بیشتر به اسناد رسمی logging بروید.

به مدیریت خطا های برنامه مراجعه کنید.

قلاب کردن در WSGI Middleware

برای افزودن میان‌افزار WSGI به برنامه Flask خود، ویژگی wsgi_app برنامه را بپیچید. برای مثال، برای اعمال میان‌افزار ProxyFix برای اجرای پشت Nginx کد زیر را ببنید:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

قرار دادن app.wsgi_app به جای app به این معنی است که app همچنان به برنامه فلاسک شما اشاره می‌کند، نه به میان‌افزار، بنابراین می‌توانید مستقیماً به استفاده و پیکربندی app ادامه دهید.

استفاده از افزونه های فلاسک

افزونه ها پکیج هایی هستند که کمک میکنند تا تکالیف مشترکی را انجام دهند. برای مثال Flask-SQLAlchemy پشتیبانی از SQLAlchemy راه تهیه میکند و کار با آن در فلاسک را آسانتر میسازد.

برای افزونه های بیشتر فلاسک افزونه ها را ببنید.

استقرار کردن به یک وب سرور

آیا برای استقرار برنامه فلاسک جدیدتان آماده اید؟ Deploying to Production با ببنید.