English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في الشرح السابق، قمنا بتعريف رؤية Django، وكتبت مثالاً بسيطاً. في هذا الفصل سنتعلم تطبيق استطلاع الشبكة، وركزنا على معالجة الاستمارات البسيطة بأقل كمية من الكود.
نحن نقوم بتحديث نموذج تفاصيل الاستطلاع ("polls/detail.html") من خلال الشرح السابق، في النموذج polls/templates/polls/detail.html يحتوي على عنصر HTML<form> بسيط:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ar.oldtoolbag.com # Date : 2020-08-08 <h1>{{ question.question_text }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="{% url 'polls:vote' question.id %}" method="post"> {% csrf_token %} {% for choice in question.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br /> {% endfor %} <input type="submit" value="تصويت" /> </form> النمذجة أعلاه تظهر اختيار كل سؤال. كل اختيار من نوع راديو مرتبط بنوع السؤال. كل اسم اختيار هو "choice". هذا يعني أن عند اختيار شخص ما لاحد من الخيارات وإرسال النموذج، سيتم إرسال بيانات POST choice=#، حيث هو هو ID للاختيار المختار. هذا هو مفهوم أساسي للنموذج HTML. لقد قمنا بضبط عمل النموذج {% url 'polls:vote' question.id %}، بالإضافة إلى ضبط method="post". من المهم جدًا استخدام method="post" (على عكس method="get")، لأن تقديم هذا الشكل سيؤدي إلى تغيير سلوك البيانات على الجانب الخلفي للخادم. هذا المقال ليس مخصصًا فقط لدjango; إنه أيضًا ممارسة جيدة في تطوير الويب. forloop.counter يعني عدد مرات تمرير العلامة التالية في الدورة نحن نقوم بإنشاء شكل POST (يمكن أن يؤدي إلى تعديل البيانات)، لذا يجب أن نهتم بتحايل الطلب عبر الموقع. ولكن لا يجب أن نقلق، لأن Django يحتوي على نظام بسيط جدًا للحماية من ذلك. على أي حال، يجب استخدام وسم النمذجة {% csrf_token %} لجميع أشكال POST للروابط الداخلية.
لقد قمنا بإنشاء إصدار افتراضي من وظيفة vote(). الآن أنشئ إصدار عملي. أضف الكود التالي إلى ملف polls/views.py:
polls/views.py ملف المحتوى كالتالي:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ar.oldtoolbag.com # Date : 2020-08-08 from django.shortcuts import get_object_or_404, render; from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse from models import Choice, Question # ... def vote(request, question_id): question = get_object_or_404(Question, pk=question_id); try: selected_choice = question.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): # فرم رأیدهی سوال مجدداً نمایش داده شود. return render(request, 'polls/detail.html', { 'question': question, 'error_message': "You didn't select a choice.", ) else: selected_choice.votes += 1 selected_choice.save() # همیشه بعد از برخورداری موفق از HttpResponseRedirect بازگردانده شود # با دادههای POST. این از ارسال دوباره دادهها جلوگیری میکند اگر یک # کاربر دکمه بازگشت Back را کلیک میکند. return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
این کد شامل چندین چیز است که هنوز در این آموزش معرفی نشدهاند:
request.POST یک شیء مشابه دیکشنری است که به شما اجازه میدهد دادههای ارسالی را از طریق نام کلید دسترسی کنید. در این حالت، request.POST['choice'] شناسه انتخاب شده choice را به عنوان یک رشته برمیگرداند. مقادیر request.POST همیشه رشته هستند.
توجه داشته باشید: Django به طور مشابه request.GET را برای دسترسی به دادههای GET ارائه میدهد – اما ما از request.POST به وضوح در کد خود استفاده میکنیم، تا مطمئن شویم که دادهها فقط از طریق فراخوانی POST تغییر میکنند.
اگر دادههای POST داده نشده باشد، request.POST['choice'] باعث ایجاد خطا KeyError میشود. کد بالا خطای KeyError و نمایش پیام خطا برای فرمهایی که 'choice' ارائه نمیدهد را بررسی میکند.
بعد از افزایش شمارش انتخاب، کد HttpResponse ریدایرکت بازمیگرداند، نه HttpResponse عادی. HttpResponseRedirect نیاز به یک پارامتر دارد: URLای که کاربر به آن ریدایرکت خواهد شد (لطفاً به زیر نگاه کنید - چگونه ما در این شرایط URL را میسازیم).
كما يشير التعليق في Python أعلاه، يجب دائمًا العودة إلى HttpResponse Redirect بعد معالجة بيانات POST بنجاح.
في هذا المثال، نستخدم HttpResponseRedirect بناءً على function reverse(). هذه function تساعد في تجنب الت编码 الثابت للURL في views. لأننا نريد توجيه التحكم إلى جزء المتغير من نمط URL للview، في هذه الحالة، باستخدام إعدادات URLconf، سيقوم function reverse() بتقديم string مثل:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ar.oldtoolbag.com # Date : 2020-08-08 "/polls/3/results/"
فيه، 3 هو قيمة question.id. ثم، سيتم استدعاء هذا URL الموجه إلى الصفحة الأخيرة في view results.
الآن، اذهب إلى عنوان URL التالي: http://127.0.0.1:8000/polls/1/ لرؤية النتائج التالية: عندما يقوم شخص بالتصويت على سؤال، يتم توجيه view() إلى صفحة النتائج للسؤال. دعنا نكتب هذا view (polls/views.py):
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ar.oldtoolbag.com # Date : 2020-08-08 from django.shortcuts import get_object_or_404, render; def results(request, question_id): question = get_object_or_404(Question, pk=question_id); return render(request, 'polls/results.html', {'question': question}));
الآن، قم بإنشاء ملف polls/results.html (polls/templates/polls/results.html) النمط:
# Filename : example.py # Copyright : 2020 By w3codebox # Author by : ar.oldtoolbag.com # Date : 2020-08-08 <h2>{{ question.question_text }}</h2> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li> {% endfor %} </ul> <a href="{% url 'polls:detail' question.id %}">تصويت مرة أخرى؟</a>
الآن، افتح /polls/1/ في المتصفح وأصوات المشكلة التي ستشاهدها يجب أن تكون محدثة في كل مرة تقوم بتصويت. إذا قمت بتقديم النموذج دون اختيار خيار، يجب أن ترى رسالة خطأ. اختر خيارًا ثم قدم النموذج، يجب أن تظهر النتيجة التالية:
أولاً، افتح polls/urls.py وعدل كما يلي:
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'), url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'), url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]