كيفية استخدام نماذج الويب في تطبيق Flask

اختار المؤلف صندوق الأموال المجانية والمفتوحة المصدر لتلقي تبرع كجزء من برنامج Write for DOnations.

مقدمة

أشكال الويب، مثل حقول النص ومناطق النص، تمنح المستخدمين القدرة على إرسال البيانات إلى تطبيقك لاستخدامها في تنفيذ إجراء، أو لإرسال مناطق نصية أكبر إلى التطبيق. على سبيل المثال، في تطبيق وسائل التواصل الاجتماعي، قد تعطي المستخدمين مربعًا حيث يمكنهم إضافة محتوى جديد إلى صفحاتهم. مثال آخر هو صفحة تسجيل الدخول، حيث تعطي المستخدم حقل نصي لإدخال اسم المستخدم وحقل كلمة المرور لإدخال كلمة المرور. الخادم (تطبيق Flask الخاص بك في هذه الحالة) يستخدم البيانات التي يقدمها المستخدم ويسجلهم إذا كانت البيانات صالحة، أو يرد برسالة مثل بيانات غير صحيحة! لإبلاغ المستخدم بأن البيانات التي قدموها غير صحيحة.

Flask هو إطار عمل ويب خفيف الوزن في لغة Python يوفر أدوات وميزات مفيدة لإنشاء تطبيقات الويب بلغة Python. في هذا البرنامج التعليمي، ستقوم ببناء تطبيق ويب صغير يوضح كيفية استخدام نماذج الويب. سيكون للتطبيق صفحة لعرض الرسائل المخزنة في قائمة Python، وصفحة لإضافة رسائل جديدة. ستستخدم أيضًا توجيه الرسائل لإبلاغ المستخدمين بخطأ عندما يقدمون بيانات غير صالحة.

المتطلبات الأساسية

الخطوة 1 – عرض الرسائل

في هذه الخطوة، ستنشئ تطبيق Flask مع صفحة فهرس لعرض الرسائل المخزنة في قائمة من القواميس البايثون.

أولاً، افتح ملفًا جديدًا يسمى app.py للتحرير:

  1. nano app.py

أضف الكود التالي داخل ملف app.py لإنشاء خادم Flask بمسار واحد:

flask_app/app.py
from flask import Flask, render_template

app = Flask(__name__)

messages = [{'title': 'Message One',
             'content': 'Message One Content'},
            {'title': 'Message Two',
             'content': 'Message Two Content'}
            ]

@app.route('/')
def index():
    return render_template('index.html', messages=messages)

احفظ وأغلق الملف.

في هذا الملف، تقوم أولاً باستيراد فئة Flask ودالة render_template() من الحزمة flask. ثم تستخدم فئة Flask لإنشاء مثيل تطبيق جديد يسمى app، مع تمرير المتغير الخاص __name__، الذي يحتاجه Flask لإعداد بعض المسارات في الخلفية. يتم تغطية عرض القوالب في الدرس كيفية استخدام القوالب في تطبيق Flask.

ثم تنشئ قائمة بايثون عالمية تسمى messages، والتي تحتوي داخلها على قواميس بايثون. كل قاموس يحتوي على مفتاحين: title لعنوان الرسالة، وcontent لمحتوى الرسالة. هذا مثال مبسط لطريقة تخزين البيانات؛ في سيناريو العالم الحقيقي، ستستخدم قاعدة بيانات تحفظ البيانات بشكل دائم وتسمح لك بالتلاعب بها بشكل أكثر كفاءة.

بعد إنشاء قائمة Python، تستخدم المُزخرف @app.route() لإنشاء دالة عرض تسمى index(). فيها، تقوم بإرجاع استدعاء للدالة render_template()، التي تُعلم Flask أن المسار يجب أن يعرض قالب HTML. تسمي هذا القالب index.html (ستنشئه لاحقًا)، وتُمرر له متغيرًا يسمى messages. هذا المتغير يحمل القائمة messages التي أعلنت عنها سابقًا كقيمة ويجعلها متاحة لقالب HTML. دوال العرض موضحة في الدرس كيفية إنشاء أول تطبيق ويب لك باستخدام Flask و Python 3.

بعد ذلك، قم بإنشاء مجلد templates في مجلد flask_app حيث يبحث Flask عن القوالب، ثم افتح ملف قالب يسمى base.html، الذي سيحتوي على الكود الذي سيرثه القوالب الأخرى لتجنب تكرار الكود:

  1. mkdir templates
  2. nano templates/base.html

أضف الكود التالي داخل ملف base.html لإنشاء القالب الأساسي مع شريط تنقل وحظوظ محتوى:

flask_app/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .message {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

احفظ وأغلق الملف.

هذا النموذج الأساسي يحتوي على كل ما تحتاجه من HTML boilerplate لإعادة استخدامه في قوالبك الأخرى. سيتم استبدال كتلة `title` لتعيين عنوان لكل صفحة، وسيتم استبدال كتلة `content` بمحتوى كل صفحة. شريط التنقل يحتوي على رابطين، أحدهما لصفحة الفهرس حيث تستخدم دالة `url_for()` للارتباط بدالة العرض `index()`، والآخر لصفحة “حول” إذا اخترت تضمين واحدة في تطبيقك.

بعد ذلك، افتح قالب يسمى `index.html`. هذا هو القالب الذي استشارته في ملف `app.py`:

  1. nano templates/index.html

أضف الكود التالي إليه:

flask_app/templates/index.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Messages {% endblock %}</h1>
    {% for message in messages %}
        <div class='message'>
            <h3>{{ message['title'] }}</h3>
            <p>{{ message['content'] }}</p>
        </div>
    {% endfor %}
{% endblock %}

احفظ وأغلق الملف.

في هذا الكود، تمتد من القالب `base.html` وتستبدل محتويات كتلة `content`. تستخدم عنوان `<h1>` يعمل أيضًا كعنوان.

تستخدم حلقة Jinja `for` في السطر `{% for message in messages %}` للمرور عبر كل رسالة في قائمة `messages`. تستخدم علامة `<div>` لاحتواء عنوان ومحتوى الرسالة. تعرض العنوان في عنوان `<h3>` والمحتوى في علامة `<p>`.

بينما تكون في مجلد `flask_app` مع تفعيل بيئة العمل الافتراضية، أعلم Flask بالتطبيق (`app.py` في هذه الحالة) باستخدام متغير البيئة `FLASK_APP`:

  1. export FLASK_APP=app

ثم قم بتعيين متغير البيئة FLASK_ENV إلى development لتشغيل التطبيق في وضع التطوير والحصول على وصول إلى مصحح الأخطاء. لمزيد من المعلومات حول مصحح الأخطاء في Flask، راجع كيفية التعامل مع الأخطاء في تطبيق Flask. استخدم الأوامر التالية للقيام بذلك (على Windows، استخدم set بدلاً من export):

  1. export FLASK_ENV=development

بعد ذلك، قم بتشغيل التطبيق:

  1. flask run

مع تشغيل خادم التطوير، قم بزيارة الرابط التالي باستخدام متصفحك:

http://127.0.0.1:5000/

سترى الرسائل في قائمة messages معروضة على صفحة الفهرس:

الآن وبعد أن قمت بإعداد تطبيق الويب الخاص بك وعرض الرسائل، ستحتاج إلى وسيلة تسمح للمستخدمين بإضافة رسائل جديدة إلى صفحة الفهرس. يتم ذلك من خلال نماذج الويب، التي ستقوم بإعدادها في الخطوة التالية.

الخطوة 2 — إعداد النماذج

في هذه الخطوة، ستقوم بإنشاء صفحة في تطبيقك تسمح للمستخدمين بإضافة رسائل جديدة إلى قائمة الرسائل عبر نموذج ويب.

اترك خادم التطوير يعمل وافتح نافذة طرفية جديدة.

أولاً، افتح ملف app.py الخاص بك:

  1. nano app.py

أضف المسار التالي إلى نهاية الملف:

flask_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    return render_template('create.html')

احفظ وأغلق الملف.

هذا المسار /create يحتوي على معامل methods مع المجموعة ('GET', 'POST') لقبول طلبات GET و POST معًا. GET و POST هي أساليب HTTP. بشكل افتراضي، يتم قبول طلبات GET فقط، والتي تستخدم لاسترداد البيانات، مثل طلب صفحة فهرس أو صفحة حول من الخادم. تُستخدم طلبات POST لتقديم البيانات إلى مسار معين، والذي يغير غالبًا البيانات على الخادم.

في هذا المثال، ستطلب صفحة create باستخدام طلب GET. ستحتوي صفحة الإنشاء على نموذج ويب بحقول إدخال وزر تقديم. عندما يملأ المستخدم النموذج وينقر على زر التقديم، يتم إرسال طلب POST إلى المسار /create. هناك تتعامل مع الطلب، وتتحقق من البيانات المقدمة للتأكد من أن المستخدم لم يقدم نموذجًا فارغًا، ثم تضيفه إلى قائمة messages.

الدالة create() تقوم حاليًا بشيء واحد فقط: تقدم قالبًا يسمى create.html عندما تتلقى طلب GET عادي. ستقوم الآن بإنشاء هذا القالب، ثم تحرير الدالة للتعامل مع طلبات POST في الخطوة التالية.

افتح ملف قالب جديد يسمى create.html:

  1. nano templates/create.html

أضف الكود التالي إليه:

flask_app/templates/create.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Add a New Message {% endblock %}</h1>
    <form method="post">
        <label for="title">Title</label>
        <br>
        <input type="text" name="title"
               placeholder="Message title"
               value="{{ request.form['title'] }}"></input>
        <br>

        <label for="content">Message Content</label>
        <br>
        <textarea name="content"
                  placeholder="Message content"
                  rows="15"
                  cols="60"
                  >{{ request.form['content'] }}</textarea>
        <br>
        <button type="submit">Submit</button>
    </form>
{% endblock %}

احفظ وأغلق الملف.

في هذا الكود، تمدد القالب `base.html` وتستبدل كتلة `content` بعنوان `<h1>` يعمل كعنوان للصفحة. في علامة `<form>`، يتم تعيين سمة `method` إلى `post` بحيث يتم إرسال بيانات النموذج إلى الخادم كطلب `POST`.

في النموذج، لديك حقل إدخال نص يسمى `title`؛ هذا هو الاسم الذي ستستخدمه في التطبيق للوصول إلى بيانات النموذج للعنوان. تعطي علامة `<input>` قيمة `{{ request.form['title'] }}`. هذا مفيد لاستعادة البيانات التي يدخلها المستخدم حتى لا تضيع عندما يحدث خطأ. على سبيل المثال، إذا نسى المستخدم ملء منطقة النص `content` المطلوبة، يتم إرسال طلب إلى الخادم وسيأتي رسالة خطأ كرد فعل، ولكن البيانات في العنوان لن تضيع لأنها ستُحفظ في الكائن العام `request`، ويمكن الوصول إليها عبر `request.form['title']`.

بعد حقل إدخال العنوان، تضيف منطقة نصية تسمى `content` بالقيمة `{{ request.form['content'] }}` لنفس الأسباب المذكورة سابقًا.

أخيرًا، لديك زر إرسال في نهاية النموذج.

الآن، مع تشغيل خادم التطوير، استخدم متصفحك للانتقال إلى المسار `/create`:

http://127.0.0.1:5000/create

سترى صفحة “إضافة رسالة جديدة” مع حقل إدخال لعنوان الرسالة، ومنطقة نصية لمحتوى الرسالة، وزر إرسال.

هذا النموذج يرسل طلب POST إلى وظيفة العرض create() الخاصة بك. ومع ذلك، لا يوجد أي كود للتعامل مع طلب POST في الوظيفة حتى الآن، لذا لا يحدث شيء بعد ملء النموذج وإرساله. في الخطوة التالية، ستتعامل مع طلب POST الوارد عندما يتم إرسال نموذج. ستتحقق مما إذا كانت البيانات المقدمة صالحة (ليست فارغة)، وتضيف عنوان الرسالة ومحتواها إلى قائمة messages.

الخطوة 3 — التعامل مع طلبات النموذج

في هذه الخطوة، ستتعامل مع طلبات النموذج من جانب التطبيق. ستصل إلى بيانات النموذج التي يقدمها المستخدم عبر النموذج الذي أنشأته في الخطوة السابقة وتضيفها إلى قائمة الرسائل. ستستخدم أيضًا توجيه الرسائل لإبلاغ المستخدمين عندما يقدمون بيانات غير صالحة. ستظهر رسالة التوجيه مرة واحدة فقط وستختفي في الطلب التالي (إذا قمت بالتنقل إلى صفحة أخرى مثلاً).

افتح ملف app.py للتحرير:

  1. nano app.py

أولاً، ستقوم باستيراد ما يلي من إطار عمل Flask:

  • الكائن العام request للوصول إلى بيانات الطلب الواردة التي سيتم تقديمها عبر نموذج HTML الذي بنيته في الخطوة السابقة.
  • الدالة url_for() لتوليد الروابط.
  • الدالة flash() لعرض رسالة عند معالجة طلب (لإبلاغ المستخدم بأن كل شيء سار بشكل جيد، أو لإبلاغهم بمشكلة إذا كانت البيانات المقدمة غير صالحة).
  • الدالة redirect() لإعادة توجيه العميل إلى مكان آخر.

أضف هذه الاستيرادات إلى السطر الأول في الملف:

flask_app/app.py
from flask import Flask, render_template, request, url_for, flash, redirect

# ...

الدالة flash() تخزن الرسائل المعروضة في جلسة المتصفح للعميل، والتي تتطلب تعيين مفتاح سري. يستخدم هذا المفتاح السري لتأمين الجلسات، مما يسمح لـ Flask بتذكر المعلومات من طلب إلى آخر، مثل الانتقال من صفحة الرسالة الجديدة إلى صفحة الفهرس. يمكن للمستخدم الوصول إلى المعلومات المخزنة في الجلسة، ولكن لا يمكنه تعديلها إلا إذا كان لديه المفتاح السري، لذا يجب ألا تسمح لأي شخص بالوصول إلى مفتاحك السري. انظر وثائق Flask للجلسات لمزيد من المعلومات.

يجب أن تكون المفتاح السري سلسلة عشوائية طويلة. يمكنك إنشاء مفتاح سري باستخدام وحدة os مع طريقة os.urandom()، التي تقوم بإرجاع سلسلة من البايتات العشوائية المناسبة للاستخدام التشفيري. للحصول على سلسلة عشوائية باستخدامها، افتح محطة جديدة وافتح قشرة بايثون التفاعلية باستخدام الأمر التالي:

  1. python

في قشرة بايثون التفاعلية، استورد وحدة os من المكتبة القياسية واستدعِ طريقة os.urandom() كما يلي:

  1. import os
  2. os.urandom(24).hex()

ستحصل على سلسلة مشابهة لما يلي:

Output
'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'

يمكنك استخدام السلسلة التي تحصل عليها كمفتاحك السري.

لتعيين المفتاح السري، أضف تهيئة SECRET_KEY إلى تطبيقك عبر كائن app.config. أضفها مباشرة بعد تعريف app قبل تعريف متغير messages:

flask_app/app.py

# ...
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'


messages = [{'title': 'Message One',
             'content': 'Message One Content'},
            {'title': 'Message Two',
             'content': 'Message Two Content'}
            ]
# ...

بعد ذلك، قم بتعديل دالة العرض create() لتبدو تمامًا كما يلي:

flask_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']

        if not title:
            flash('Title is required!')
        elif not content:
            flash('Content is required!')
        else:
            messages.append({'title': title, 'content': content})
            return redirect(url_for('index'))

    return render_template('create.html')

في عبارة if تضمن أن الكود الذي يليها يتم تنفيذه فقط عندما يكون الطلب طلب POST من خلال المقارنة request.method == 'POST'.

ثم تستخرج العنوان والمحتوى المقدم من كائن request.form الذي يمنحك الوصول إلى بيانات النموذج في الطلب. إذا لم يتم تقديم العنوان، فسيتم استيفاء الشرط if not title. في هذه الحالة، تعرض رسالة للمستخدم يُعلمون فيها أن العنوان مطلوب باستخدام وظيفة flash(). هذا يضيف الرسالة إلى قائمة الرسائل المنبثقة. ستعرض هذه الرسائل لاحقًا على الصفحة كجزء من قالب base.html. وبالمثل، إذا لم يتم تقديم المحتوى، فسيتم استيفاء الشرط elif not content. إذا كان الأمر كذلك، يمكنك إضافة الرسالة 'Content is required!' إلى قائمة الرسائل المنبثقة.

إذا تم تقديم العنوان ومحتوى الرسالة بشكل صحيح، يمكنك استخدام السطر messages.append({'title': title, 'content': content}) لإضافة قاموس جديد إلى قائمة messages، مع العنوان والمحتوى الذي قدمه المستخدم. ثم تستخدم وظيفة redirect() لإعادة توجيه المستخدمين إلى صفحة الفهرس. تستخدم وظيفة url_for() للربط بصفحة الفهرس.

احفظ وأغلق الملف.

الآن، انتقل إلى المسار /create باستخدام متصفح الويب الخاص بك:

http://127.0.0.1:5000/create

املأ النموذج بعنوان من اختيارك وبعض المحتوى. بمجرد تقديم النموذج، سترى الرسالة الجديدة مدرجة على صفحة الفهرس.

أخيرًا، ستعرض الرسائل المنبثقة وتضيف رابطًا لصفحة “رسالة جديدة” إلى شريط التنقل في قالب base.html للوصول السهل إلى هذه الصفحة الجديدة. افتح ملف القالب الأساسي:

  1. nano templates/base.html

عدّل الملف بإضافة علامة <a> جديدة بعد رابط FlaskApp في شريط التنقل داخل علامة <nav>. ثم أضف حلقة for جديدة مباشرة أعلى كتلة content لعرض الرسائل المحملة أسفل شريط التنقل. تتوفر هذه الرسائل في الدالة الخاصة get_flashed_messages() التي يوفرها Flask. ثم أضف سمة صنف تسمى alert إلى كل رسالة وأعطيها بعض الخصائص الأنماطية داخل علامة <style>:

flask_app/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .message {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

        .alert {
            padding: 20px;
            margin: 5px;
            color: #970020;
            background-color: #ffd5de;
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="{{ url_for('create') }}">Create</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% for message in get_flashed_messages() %}
            <div class="alert">{{ message }}</div>
        {% endfor %}
        {% block content %} {% endblock %}
    </div>
</body>
</html>

احفظ وأغلق الملف، ثم أعد تحميل https://127.0.0.1:5000 في متصفحك. سيحتوي شريط التنقل الآن على عنصر “إنشاء” يرتبط بالمسار /create.

لرؤية كيفية عمل الرسائل المحملة، انتقل إلى صفحة “إنشاء”، وانقر على زر الإرسال دون ملء الحقلين. ستتلقى رسالة تبدو كالتالي:

ارجع إلى صفحة الفهرس وسترى أن الرسائل المحملة أسفل شريط التنقل تختفي، على الرغم من أنها معروضة كجزء من القالب الأساسي. لو لم تكن رسائل محملة، فسيتم عرضها أيضًا في صفحة الفهرس، لأنها ترث أيضًا من القالب الأساسي.

جرب تقديم النموذج مع عنوان ولكن بدون محتوى. سترى الرسالة “المحتوى مطلوب!” اضغط على رابط FlaskApp في شريط التنقل للعودة إلى صفحة الفهرس، ثم اضغط على زر العودة للرجوع إلى صفحة الإنشاء. ستلاحظ أن الرسالة لا تزال موجودة. هذا يعمل فقط إذا قمت بالنقر على زر العودة، لأنه يحفظ الطلب السابق. النقر على رابط الإنشاء في شريط التنقل سيرسل طلبًا جديدًا، مما يمسح النموذج، ونتيجة لذلك، ستختفي الرسالة الموجهة.

لقد تعلمت الآن كيفية استلام مدخلات المستخدم، وكيفية التحقق من صحتها، وكيفية إضافتها إلى مصدر بيانات.

ملاحظة:
الرسائل التي تضيفها إلى قائمة messages ستختفي عندما يتم إيقاف الخادم، لأن قوائم بايثون يتم حفظها فقط في الذاكرة، لحفظ رسائلك بشكل دائم، ستحتاج إلى استخدام قاعدة بيانات مثل SQLite. تحقق من كيفية استخدام وحدة sqlite3 في Python 3 لتعلم كيفية استخدام SQLite مع Python.

خاتمة

لقد أنشأت تطبيق Flask حيث يمكن للمستخدمين إضافة رسائل إلى قائمة رسائل معروضة على صفحة الفهرس. لقد أنشأت نموذج ويب، وتعاملت مع البيانات التي يقدمها المستخدم عبر النموذج، وأضفتها إلى قائمة الرسائل. كما استخدمت رسائل موجهة لإبلاغ المستخدم عندما يقدمون بيانات غير صالحة.

إذا كنت ترغب في قراءة المزيد عن Flask، تفقد الدروس الأخرى في سلسلة Flask.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-web-forms-in-a-flask-application