Table of Contents
فرمها در برنامههای وب
در بخشهای قبلی این فصل، با مفهوم کلی توسعهٔ وب و فریمورک Flask آشنا شدهاید و احتمالاً یک وبسرور ساده و مسیرها (routes) را ساختهاید. در این بخش روی یک موضوع مشخص تمرکز میکنیم: گرفتن ورودی از کاربر از طریق فرمهای HTML و پردازش آن در پایتون (Flask).
هدف این بخش:
- ساخت یک فرم ساده (مثلاً فرم ورود نام کاربر)
- ارسال فرم به سرور (روشهای
GETوPOST) - دریافت و خواندن داده در Flask
- اعتبارسنجی سادهٔ ورودی
- نمایش نتیجه به کاربر
مرور بسیار کوتاه: مسیر و تابع در Flask
فرض میکنیم تا اینجا یک برنامهٔ پایهٔ Flask مانند زیر را میشناسید:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "سلام دنیا!"
if __name__ == "__main__":
app.run(debug=True)اکنون میخواهیم به جای متن ساده، فرمها را پردازش کنیم.
ساخت یک فرم HTML ساده
برای گرفتن ورودی از کاربر در وب، از فرم HTML استفاده میکنیم. یک فرم بسیار ساده که فقط نام کاربر را میگیرد:
<form action="/hello" method="post">
<label>نام شما:</label>
<input type="text" name="username">
<button type="submit">ارسال</button>
</form>نکات مهم این فرم:
- ویژگی
action="/hello"
میگوید وقتی فرم ارسال شد، درخواست به آدرس/helloفرستاده شود. - ویژگی
method="post"
نوع درخواست را مشخص میکند. اینجا ازPOSTاستفاده میکنیم که برای فرستادن داده به سرور رایج است. - ویژگی
name="username"
بسیار مهم است. این نام، کلیدی است که در سمت پایتون برای خواندن مقدار این فیلد استفاده میکنیم.
در Flask معمولاً این فرم را داخل یک قالب (template) میگذاریم، اما در این فصل قبلاً با قالبها آشنا شدهاید؛ اینجا تمرکز روی ورودی و پردازش است، نه جزئیات قالببندی.
دریافت دادهٔ فرم در Flask با request
برای خواندن دادهٔ فرم در سمت سرور، در Flask از شیء request استفاده میکنیم.
ابتدا باید آن را وارد کنیم:
from flask import Flask, request
سپس مسیری میسازیم که فرم را دریافت کند. مثلاً مسیری برای /hello که هم فرم را نشان دهد و هم جواب را:
from flask import Flask, request
app = Flask(__name__)
@app.route("/hello", methods=["GET", "POST"])
def hello():
if request.method == "POST":
# فرم ارسال شده است
username = request.form.get("username")
return f"سلام، {username}!"
else:
# اولین بار صفحه را با فرم نمایش بده
return """
<form action="/hello" method="post">
<label>نام شما:</label>
<input type="text" name="username">
<button type="submit">ارسال</button>
</form>
"""
if __name__ == "__main__":
app.run(debug=True)نکات:
- در
@app.routeازmethods=["GET", "POST"]استفاده کردهایم:
یعنی این مسیر هم درخواستهایGET(نمایش فرم) و همPOST(پردازش فرم) را قبول میکند. request.methodرا بررسی میکنیم:- اگر
"POST"بود یعنی کاربر روی دکمهٔ ارسال (Submit) کلیک کرده و فرم را فرستاده است. - اگر
"GET"بود، به کاربر فقط خود فرم را نشان میدهیم. request.form.get("username")
مقدار فیلدی را میگیرد که در فرمname="username"داشتیم.
این سادهترین شکل پردازش فرم در Flask است.
GET در برابر POST در فرمها
فرمها معمولاً با دو روش اصلی ارسال میشوند: GET و POST.
روش GET
اگر در فرم بنویسید:
<form action="/search" method="get">- دادهها در نوار آدرس URL ظاهر میشوند، مثل:
http://localhost:5000/search?q=python
- در Flask آنها را معمولاً با
request.argsمیخوانیم، نهrequest.form.
@app.route("/search", methods=["GET"])
def search():
query = request.args.get("q")
return f"نتیجهٔ جستجو برای: {query}"
روش GET معمولاً مناسب است برای:
- جستوجوها
- فیلتر کردن لیستها
- درخواستهایی که فقط اطلاعات میگیرند و چیزی را در سرور تغییر نمیدهند.
روش POST
اگر در فرم بنویسید:
<form action="/login" method="post">- دادهها در بدنهٔ درخواست (body) ارسال میشوند، نه در URL.
- در Flask با
request.formخوانده میشوند.
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
user = request.form.get("user")
password = request.form.get("password")
return f"ورود با نام کاربری: {user}"
return """
<form action="/login" method="post">
<label>نام کاربری:</label>
<input type="text" name="user">
<label>رمز عبور:</label>
<input type="password" name="password">
<button type="submit">ورود</button>
</form>
"""
روش POST مناسب است برای:
- فرمهای ورود (Login)
- ثبتنام
- ارسال فرمهای بلند
- هر کاری که اطلاعات را تغییر یا ایجاد میکند.
خواندن چندین فیلد از فرم
در یک فرم معمولاً بیش از یک فیلد داریم. مثال: فرم ثبتنام ساده.
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form.get("username")
email = request.form.get("email")
age = request.form.get("age")
return f"ثبتنام انجام شد: {username} ({email})، سن: {age}"
return """
<h1>فرم ثبتنام</h1>
<form method="post">
<label>نام کاربری:</label>
<input type="text" name="username"><br>
<label>ایمیل:</label>
<input type="email" name="email"><br>
<label>سن:</label>
<input type="number" name="age"><br>
<button type="submit">ثبتنام</button>
</form>
"""در این مثال:
- همهٔ فیلدها را با
request.form.get(...)میخوانیم. - نام هر فیلد باید با مقدار
nameدر تگ<input>هماهنگ باشد.
اعتبارسنجی سادهٔ ورودی (Validation مقدماتی)
کاربر ممکن است:
- فیلدی را خالی بگذارد
- مقدار نامعتبر بدهد (مثلاً سن منفی)
مرحلهای بسیار مهم در پردازش ورودی، بررسی و اعتبارسنجی آن است.
یک مثال ساده:
@app.route("/age-check", methods=["GET", "POST"])
def age_check():
if request.method == "POST":
age_text = request.form.get("age", "").strip()
if age_text == "":
return "لطفاً سن خود را وارد کنید."
# تلاش برای تبدیل به عدد
try:
age = int(age_text)
except ValueError:
return "سن باید عدد صحیح باشد."
if age < 0:
return "سن نمیتواند منفی باشد."
elif age < 18:
return "شما زیر ۱۸ سال هستید."
else:
return "شما ۱۸ سال یا بیشتر دارید."
return """
<form method="post">
<label>سن شما:</label>
<input type="text" name="age">
<button type="submit">بررسی</button>
</form>
"""نکات مهم:
- همیشه فرض کنید کاربر ممکن است هر چیزی وارد کند.
- از
try/exceptبرای تبدیل متن به عدد استفاده کنید (فصل خطاها این را کاملتر توضیح میدهد). - در صورت خطا، پیام مناسب به کاربر برگردانید.
ارسال دوبارهٔ فرم به همراه پیام خطا
در عمل بهتر است اگر خطایی در ورودی وجود داشت، فرم را همراه پیام خطا دوباره نشان دهیم، نه فقط متن خالی.
برای این کار در پروژههای واقعی از قالبها و render_template استفاده میکنیم. یک مثال ساده که ساختار کلی را نشان میدهد (بدون رفتن عمیق به جزئیات قالبها):
فایل app.py:
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route("/contact", methods=["GET", "POST"])
def contact():
error = ""
name = ""
message = ""
if request.method == "POST":
name = request.form.get("name", "").strip()
message = request.form.get("message", "").strip()
if not name:
error = "لطفاً نام خود را وارد کنید."
elif len(message) < 10:
error = "پیام باید حداقل ۱۰ کاراکتر باشد."
else:
# در اینجا مثلاً میتوان پیام را در فایل ذخیره کرد
return "پیام شما ارسال شد. ممنون!"
return render_template("contact.html", error=error, name=name, message=message)
if __name__ == "__main__":
app.run(debug=True)
فایل templates/contact.html (فقط برای درک جریان):
<!doctype html>
<html>
<body>
<h1>فرم تماس</h1>
{% if error %}
<p style="color:red;">{{ error }}</p>
{% endif %}
<form method="post">
<label>نام:</label>
<input type="text" name="name" value="{{ name }}"><br>
<label>پیام:</label><br>
<textarea name="message">{{ message }}</textarea><br>
<button type="submit">ارسال</button>
</form>
</body>
</html>فقط نکات مرتبط با فرم:
- اگر خطا باشد، متغیر
errorدر قالب نشان داده میشود. - مقادیر قبلی
nameوmessageدر ورودیها قرار داده میشود تا کاربر دوباره آنها را تایپ نکند. - این الگو، رفتار رایج فرمها در وب است.
ورودیهایی که چند مقدار دارند (checkbox, select multiple)
گاهی یک فیلد میتواند چند مقدار داشته باشد؛ مثلاً چند تیک در checkbox.
فرم:
<form method="post">
<p>زبانهای مورد علاقهٔ شما:</p>
<label><input type="checkbox" name="languages" value="Python"> Python</label>
<label><input type="checkbox" name="languages" value="JavaScript"> JavaScript</label>
<label><input type="checkbox" name="languages" value="C++"> C++</label>
<button type="submit">ارسال</button>
</form>
در Flask برای خواندن همهٔ مقدارها باید از getlist استفاده کنیم:
@app.route("/languages", methods=["GET", "POST"])
def languages():
if request.method == "POST":
selected = request.form.getlist("languages")
return f"زبانهای انتخابشده: {', '.join(selected)}"
return """
<form method="post">
<p>زبانهای مورد علاقهٔ شما:</p>
<label><input type="checkbox" name="languages" value="Python"> Python</label>
<label><input type="checkbox" name="languages" value="JavaScript"> JavaScript</label>
<label><input type="checkbox" name="languages" value="C++"> C++</label>
<button type="submit">ارسال</button>
</form>
"""
اگر از request.form.get("languages") استفاده کنید، فقط اولین مقدار را میگیرید. getlist همهٔ آنها را به صورت یک لیست برمیگرداند.
جمعبندی
در این بخش یاد گرفتید که:
- چطور یک فرم HTML ساده بسازید (
<form>,<input>,method,action،name). - تفاوت کلی بین روشهای
GETوPOSTدر ارسال فرم. - چگونه با
request.formوrequest.argsدادهٔ فرم را در Flask بخوانید. - چطور چندین فیلد را پردازش و ورودیها را به شکل ساده اعتبارسنجی کنید.
- الگوی رایج: در
GETفرم را نشان دهید، درPOSTداده را بررسی و نتیجه را برگردانید. - در صورت نیاز برای فیلدهای چند انتخابی از
request.form.getlistاستفاده کنید.
این مهارتها پایهٔ بیشتر برنامههای وب تعاملی با پایتون هستند. در ادامهٔ فصل، میتوانید از همین ورودیها برای ساخت APIهای ساده یا پروژههای وب کوچک استفاده کنید.