آموزش جنگو (Basic) : جلسه ده | generic view

در این جلسه به بررسی نحوه ایجاد یک generic view در جنگو می پردازیم . با ما همراه باشید . آموزش جنگو : جلسه ده | generic viewایجاد generic view ,کد کمتر و خواناترویو های ()detail و ()results بسیار کوتاه و شبیه به هم هستند . این بخاطر این است که کاری که انها انجام میدهند , تقریبا یکسان است و تنها ممکن است جدول دیتابیس و نوع جستجو (query) آنها با یکدیگر تفاوت داشته باشد.این ویو ها فرایندی را انجام می دهند که در تمامی سطح وب به طور معمول اجرا میشود :گرفتن اطلاعات و رکورد ها از دیتابیس با توجه به پارامتری که در url به آنها ارسال شده است و سپس لود کردن یک تمپلیت و رندر کردن آن (یعنی متغییر ها نیز به تمپلیت ارسال شوند ) . به دلیل فراوانی این فرایند جنگو برای شما راه کوتاهی قرار داده است تا کد کمتر و تمیز تری بنویسید . این راه ,استفاده از generic views است .این سیستم (generic views system) کار شما را تا جایی اسان میکند که حتی نیازی به نوشتن کد پایتون برای یک ویو ندارید و فقط کافیست یک کلاس برای آن ایجاد کنید . برای ایجاد generic views باید چند گام کوتاه برداریم :1- تغییراتی در فایل polls/urls.py ایجاد کنیم .2-کمی از کد های polls/views.py را حذف کنیم .3-ویو های جدیدی بر اساس generic view ایجاد کنیم .اصلاح آدرس ها (polls/urls.py)فایل مربوط به urls در اپ خود را باز کنید و آن را به این صورت تغییر دهید .from django.urls import path from . import views app_name = 'polls' urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('<int:pk>/', views.DetailView.as_view(), name='detail'), path('<int:pk>/results/', views.ResultsView.as_view(), name='results'), path('<int:question_id>/vote/', views.vote, name='vote'), ]نکته : توجه داشته باشید که مقدار <int:question_id> به <int:pk> تغییر پیدا کرده است . (همانطور که اشاره کرده بودیم این دو تفاوت زیادی با هم ندارند و در عمل هر دو به id رکورد ما اشاره میکنند )اصلاح ویو ها (polls/views.py)حال ما قرار است ویو های ()index() , detail() , results را حذف کنیم و به جای آنها generic view ایجاد کنیم. به این منظور فایل polls/views.py را باز کنید و تغییرات زیر را در آن اعمال کنید. (ویو ()vote تغییری نخواهد کرد پس آن را پاک نکنید! )from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import generic from .models import Choice, Question class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): &quot&quot&quotReturn the last five published questions.&quot&quot&quot return Question.objects.order_by('-pub_date')[:5] class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' def vote(request, question_id): ... #این ویو همان کد قبلی را خواهد داشت و تغییری در ان نباید ایجاد کنید هر یک از generic views یک کلاس هستند از کلاس generic ارث بری میکنند . ما در اینجا از دو نوع کلاس generic استفاده کردیم : listView و DetailView. هر کدام از آنها کاری را انجام می دهند که یکی از این دو کار است : نشان دادن یک لیست از رکورد ها ,نشان دادن یک صفحه جزییات از هر رکورد !نکته مهم این است که هر کدام از generic views نیاز دارند تا بدانند دقیقا بر روی کدام مدل یا جدول از دیتابیس باید عملیاتی را انجام بدهند . این کار را به وسیله تعریف کردن متغییر model در درون آنها انجام میدهیم . (نکته ویژه : generic views فقط میتوانند یکی از دو عملیاتی که در صفحه قبل گفته شد را انجام بدهند . بنابراین اگر نیاز بود تا فرمی را ایجاد کنید و بر روی اطلاعات آن پیمایش کنید ,شما نمیتوانید از generic views استفاده کنید. )دلیل استفاده از pk در فایل urls این است که DetailView مقدار pk یا همان primary key که در واقع مقدار id رکورد ما است را به عنوان ورودی از url دریافت میکنند و به وسیله آن برای شما پاسخ یا همان صفحه جزییات را میاورند .نکته دیگری که باید در مورد generic view بدانید, تعریف کردن متغییر template_name است . DetailView به طور پیش فرض در پوشه تمپلیت ها به دنبال تمپلیتی با نام app name>/<model name>_detail> میگردند . برای مثال در اینجا : polls/question_detail.htmlدلیل تعریف متغییر template_name این است که شما به جنگو بگویید تا از یک تمپلیت شخصی سازی شده استفاده کند . همچنین در فایل polls/views.py ما دو ویو شبیه به هم داریم که هر دو مقدار متغییر model در آنها یکی است و هر دو DetailView هستند . این روش به شما کمک میکند تا مقدار خروجی آنها را کنترل کنید و به جنگو بگویید هر کدام دقیقا چه چیزهایی یا مقادیری از مدل question را باید به شما نمایش دهند (این کار را در فرانت اند و با تگ های تمپلیت ها انجام میدهید ).همچنین در مورد ListView نیز این مورد صدق میکند . آنها در پوشه تمپلیت ها به دنبال تمپلیتی با نام app_name>/<model name>_list> میگردند . برای مثال : polls/question_list.htmlنکته آخر این است که در قسمت های قبلی هر تمپلیت با مقدار question و latest_question_list در قسمت context خود رندر می شد و در generic view شما همچین چیزی را ندارید . باید بگوییم که در DetailView به دلیل اینکه شما متغییر model را تعریف کرده اید ,جنگو با استفاده از مقدار متغییر (question) میتواند نام مناسبی را برای متغییر های درون context انتخاب کند (در واقع همان question را به عنوان متغییر به تمپلیت ارسال میکند) ولی در خصوص ListView ما متغییری را با نام context_object_name تعریف کرده ایم که به شما اجازه می دهد تا برای ویو خود ,مقدار نام متغییر درون context را تعیین کنید که در اینجا ما آن را latest_question_list گذاشتیم . به صورت پیش فرض این ویو نام متغییر درون context را باید question_list نامگذاری می کرد که ما این را با تعریف آن متغییر تغییر داده ایم .در این جلسه کمی پروژه قبلی خود را اصلاح کردیم و آن را بهبود بخشیدیم . همچنین با مفهوم و نحوه ساخت یک generic view در جنگو آشنا شدیم . در جلسه بعدی به نحوه کار با تست (test) در جنگو خواهیم پرداخت .