Django 2.1 - Writing your first Django app, part 3

अपना पहला Django ऐप लिखना, भाग 3




django

अपना पहला Django ऐप लिखना, भाग 3

यह ट्यूटोरियल शुरू होता है जहां ट्यूटोरियल 2 ने छोड़ दिया। हम वेब-पोल एप्लिकेशन को जारी रख रहे हैं और सार्वजनिक इंटरफ़ेस बनाने पर ध्यान केंद्रित करेंगे - "विचार।"

अवलोकन

एक दृश्य आपके Django एप्लिकेशन में वेब पेज का एक "प्रकार" है जो आम तौर पर एक विशिष्ट कार्य करता है और एक विशिष्ट टेम्पलेट होता है। उदाहरण के लिए, एक ब्लॉग अनुप्रयोग में, आपके पास निम्नलिखित विचार हो सकते हैं:

  • ब्लॉग मुखपृष्ठ - नवीनतम कुछ प्रविष्टियाँ प्रदर्शित करता है।
  • प्रवेश "विस्तार" पृष्ठ - एकल प्रविष्टि के लिए पर्मलिंक पृष्ठ।
  • वर्ष-आधारित संग्रह पृष्ठ - दिए गए वर्ष में प्रविष्टियों के साथ सभी महीनों को प्रदर्शित करता है।
  • माह-आधारित संग्रह पृष्ठ - दिए गए महीने में प्रविष्टियों के साथ सभी दिन प्रदर्शित करता है।
  • दिन-आधारित संग्रह पृष्ठ - दिए गए दिन में सभी प्रविष्टियों को प्रदर्शित करता है।
  • टिप्पणी कार्रवाई - किसी दिए गए प्रविष्टि के लिए टिप्पणी पोस्टिंग संभालती है।

हमारे मतदान आवेदन में, हमारे पास निम्नलिखित चार विचार होंगे:

  • प्रश्न "इंडेक्स" पृष्ठ - नवीनतम कुछ प्रश्नों को प्रदर्शित करता है।
  • प्रश्न "विस्तार" पृष्ठ - एक प्रश्न पाठ प्रदर्शित करता है, जिसमें कोई परिणाम नहीं है लेकिन वोट करने के लिए एक फॉर्म है।
  • प्रश्न "परिणाम" पृष्ठ - एक विशेष प्रश्न के लिए परिणाम प्रदर्शित करता है।
  • वोट एक्शन - एक विशेष प्रश्न में किसी विशेष पसंद के लिए मतदान को संभालता है।

Django में, वेब पेज और अन्य सामग्री विचारों द्वारा वितरित की जाती हैं। प्रत्येक दृश्य को एक साधारण पायथन फ़ंक्शन (या विधि, वर्ग-आधारित विचारों के मामले में) द्वारा दर्शाया गया है। Django उस URL की जांच करके एक दृश्य का चयन करेगा जो अनुरोध किया गया है (सटीक होने के लिए, डोमेन नाम के बाद URL का हिस्सा)।

अब वेब पर आपके समय में आप “ME2 / Sites / dirmod.mat; sid = & type = gen & mod = Core + Pages & gid = A6CD4967199A42D9BBB1B” जैसी सुंदरियों के साथ आए होंगे। आपको यह जानकर प्रसन्नता होगी कि Django हमें उससे कहीं अधिक सुंदर URL पैटर्न की अनुमति देता है।

URL पैटर्न केवल URL का सामान्य रूप है - उदाहरण के लिए: /newsarchive/<year>/<month>/

URL को किसी दृश्य से प्राप्त करने के लिए, Django उपयोग करता है जिसे 'URLconfs' के रूप में जाना जाता है। URLconf विचारों के URL पैटर्न को मैप करता है।

यह ट्यूटोरियल URLconfs के उपयोग में बुनियादी निर्देश प्रदान करता है, और आप अधिक जानकारी के लिए URL प्रेषण का उल्लेख कर सकते हैं।

अधिक विचार लिखना

अब हम polls/views.py कुछ और विचार जोड़ते हैं। ये विचार थोड़ा अलग हैं, क्योंकि वे एक तर्क लेते हैं:

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

निम्नलिखित path() कॉल को जोड़कर इन नए विचारों को polls.urls मॉड्यूल में वायर करें:

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

अपने ब्राउज़र में "/ चुनाव / 34 /" पर एक नज़र डालें। यह detail() विधि चलाएगा और URL में आपके द्वारा प्रदान की जाने वाली आईडी को प्रदर्शित करेगा। “/ चुनाव / 34 / परिणाम /” और “/ चुनाव / 34 / वोट /” भी आज़माएं - ये प्लेसहोल्डर परिणाम और मतदान पृष्ठ प्रदर्शित करेंगे।

जब कोई आपकी वेबसाइट से एक पृष्ठ का अनुरोध करता है - कहते हैं, "/ चुनाव / 34 /", Django mysite.urls पायथन मॉड्यूल को लोड करेगा क्योंकि यह ROOT_URLCONF सेटिंग द्वारा इंगित किया गया है। यह urlpatterns नाम के वैरिएबल को urlpatterns और पैटर्न को क्रम में urlpatterns'polls/' पर मैच खोजने के बाद, यह मिलान पाठ ( "polls/" ) को बंद कर देता है और शेष पाठ - "34/" - को आगे की प्रक्रिया के लिए 'पोलसेयर्स' URLconf को भेजता है। वहाँ यह '<int:question_id>/' मेल खाता है, जिसके परिणामस्वरूप detail() को कॉल किया जाता detail() तरह देखें:

detail(request=<HttpRequest object>, question_id=34)

question_id=34 भाग <int:question_id> से आता है। URL के भाग कोष्ठक "कैप्चर" का उपयोग करते हुए इसे व्यू फ़ंक्शन के लिए एक कीवर्ड तर्क के रूप में भेजता है। :question_id> String_ का हिस्सा स्ट्रिंग का नाम उस नाम को परिभाषित करता है जिसका उपयोग मिलान किए गए पैटर्न की पहचान करने के लिए किया जाएगा, और <int: हिस्सा एक कनवर्टर है जो यह निर्धारित करता है कि URL पथ के इस हिस्से से किन पैटर्नों का मिलान होना चाहिए।

URL cruft को जोड़ने की कोई आवश्यकता नहीं है जैसे .html - जब तक आप नहीं चाहते हैं, जिस स्थिति में आप ऐसा कुछ कर सकते हैं:

path('polls/latest.html', views.index),

लेकिन, ऐसा मत करो। यह मूर्खता है।

उन विचारों को लिखें जो वास्तव में कुछ करते हैं

प्रत्येक दृश्य दो चीजों में से एक करने के लिए ज़िम्मेदार है: एक HttpResponse ऑब्जेक्ट को अनुरोधित पृष्ठ के लिए सामग्री को वापस करना, या Http404 जैसे अपवाद को Http404 । बाकी आप पर निर्भर करता है।

आपका दृश्य किसी डेटाबेस से रिकॉर्ड पढ़ सकता है, या नहीं। यह Django - या तीसरे पक्ष के पायथन टेम्पलेट सिस्टम जैसे टेम्पलेट सिस्टम का उपयोग कर सकता है - या नहीं। यह एक पीडीएफ फाइल उत्पन्न कर सकता है, एक्सएमएल आउटपुट कर सकता है, मक्खी पर एक जिप फाइल बना सकता है, जो कुछ भी आप चाहते हैं, आप जो भी पाइथन लाइब्रेरी चाहते हैं उसका उपयोग कर सकते हैं।

सभी Django चाहता है कि HttpResponse । या एक अपवाद।

क्योंकि यह सुविधाजनक है, आइए Django के अपने डेटाबेस एपीआई का उपयोग करें, जिसे हमने ट्यूटोरियल 2 में कवर किया है। प्रकाशन index() , एक नए index() दृश्य में एक छुरा है, जो सिस्टम में नवीनतम 5 सर्वेक्षणों को प्रदर्शित करता है, जो अल्पविराम द्वारा अलग किए गए हैं:

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

# Leave the rest of the views (detail, results, vote) unchanged

हालाँकि, यहाँ एक समस्या है: पृष्ठ का डिज़ाइन दृश्य में कठिन-कूटबद्ध है। यदि आप पृष्ठ को देखने का तरीका बदलना चाहते हैं, तो आपको इस पायथन कोड को संपादित करना होगा। तो आइए Django के टेम्प्लेट सिस्टम का उपयोग करके डिज़ाइन को पाइथन से अलग करने के लिए एक टेम्प्लेट बनाकर देखें जिसे व्यू उपयोग कर सकते हैं।

सबसे पहले, अपने polls निर्देशिका में templates नामक एक निर्देशिका बनाएं। Django वहाँ में टेम्पलेट्स के लिए दिखेगा।

आपकी परियोजना की सेटिंग सेटिंग बताती है कि Django टेम्प्लेट को कैसे लोड और प्रस्तुत करेगा। डिफ़ॉल्ट सेटिंग्स फ़ाइल एक DjangoTemplates बैकएंड को कॉन्फ़िगर करती है जिसका APP_DIRS विकल्प True सेट है। कन्वेंशन द्वारा DjangoTemplates प्रत्येक INSTALLED_APPS में "टेम्प्लेट" सबडायरेक्ट के लिए दिखता है।

आपके द्वारा अभी-अभी बनाए गए templates डायरेक्टरी के भीतर, polls नामक एक और डायरेक्टरी बनाते हैं, और उसके भीतर एक फाइल बनाते हैं, जिसे index.html कहा जाता है। दूसरे शब्दों में, आपका टेम्प्लेट polls/templates/polls/index.htmlpolls/templates/polls/index.html होना चाहिए। ऊपर बताए अनुसार app_directories टेम्प्लेट लोडर कैसे काम करता है, इस कारण से आप Django के भीतर इस polls/index.html को केवल polls/index.html app_directoriesapp_directories रूप में देख सकते हैं।

टेम्पलेट नाम स्थान

अब हम अपने टेम्प्लेट को सीधे polls/templates में डालने के बजाय दूर जाने में सक्षम हो सकते हैं (एक और polls सबडायरेक्ट बनाने के बजाय), लेकिन यह वास्तव में एक बुरा विचार होगा। Django पहला टेम्प्लेट चुनेगा जिसमें यह पता चलता है कि किसका नाम मेल खाता है, और यदि आपके पास एक अलग एप्लिकेशन में समान नाम वाला टेम्प्लेट है, तो Django उन दोनों के बीच अंतर करने में असमर्थ होगा। हमें सही तरीके से Django को इंगित करने में सक्षम होने की आवश्यकता है, और यह सुनिश्चित करने का सबसे आसान तरीका उन्हें नाम स्थान देना है। यही है, उन टेम्पलेट्स को आवेदन के लिए नामित एक और निर्देशिका के अंदर डालकर।

उस टेम्पलेट में निम्नलिखित कोड डालें:

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

अब टेम्प्लेट का उपयोग करने के लिए अपने index व्यू को polls/views.py व्यू polls/views.py में अपडेट करें:

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

वह कोड polls/index.html नामक टेम्प्लेट को लोड करता है और इसे एक संदर्भ देता है। संदर्भ पायथन ऑब्जेक्ट्स के लिए एक शब्दकोश मैपिंग टेम्प्लेट चर नाम है।

अपने ब्राउज़र को "/ चुनाव /" पर इंगित करके पृष्ठ को लोड करें, और आपको ट्यूटोरियल 2 से "व्हाट्स अप" प्रश्न युक्त एक बुलेट-सूची देखनी चाहिए। लिंक प्रश्न के विवरण पृष्ठ पर इंगित करता है।

एक शॉर्टकट: render()

टेम्प्लेट लोड करना, एक संदर्भ भरना और प्रस्तुत टेम्पलेट के परिणाम के साथ एक HttpResponse ऑब्जेक्ट वापस करना बहुत ही सामान्य मुहावरा है। Django एक शॉर्टकट प्रदान करता है। यहां पूरा index() देखें, फिर से लिखा गया है:

from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

ध्यान दें कि एक बार जब हम इन सभी दृश्यों में ऐसा कर लेते हैं, तो हमें अब loader और HttpResponse आयात करने की आवश्यकता नहीं है (यदि आप अभी भी detail , results और vote लिए स्टब विधियाँ चाहते हैं तो HttpResponse रखना चाहेंगे)।

render() फ़ंक्शन अनुरोध ऑब्जेक्ट को इसके पहले तर्क के रूप में लेता है, एक टेम्पलेट का नाम इसके दूसरे तर्क के रूप में और इसके वैकल्पिक तीसरे तर्क के रूप में एक शब्दकोश। यह दिए गए संदर्भ के साथ दिए गए टेम्पलेट के HttpResponse ऑब्जेक्ट देता है।

404 त्रुटि उठाना

अब, आइए प्रश्न विस्तार से देखें - वह पृष्ठ जो किसी दिए गए जनमत के लिए प्रश्न पाठ प्रदर्शित करता है। यहाँ देखें:

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

यहाँ नई अवधारणा: यदि अनुरोधित आईडी के साथ कोई प्रश्न मौजूद नहीं है, तो दृश्य Http404 अपवाद को जन्म देता है।

हम इस बात पर चर्चा करेंगे कि आप उस polls/detail.html में क्या डाल सकते हैं।

{{ question }}

आप अभी के लिए शुरू कर देंगे।

एक शॉर्टकट: get_object_or_404()

यदि वस्तु का अस्तित्व नहीं है, तो उसे get() और get() Http404 उठाना एक बहुत ही सामान्य मुहावरा है। Django एक शॉर्टकट प्रदान करता है। यहां detail() दृश्य, फिर से लिखा गया है:

from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

get_object_or_404() फ़ंक्शन अपने पहले तर्क के रूप में एक Django मॉडल और कीवर्ड तर्कों की एक मनमानी संख्या लेता है, जिसे वह मॉडल के प्रबंधक के get() फ़ंक्शन में पास करता है। यदि वस्तु मौजूद नहीं है तो यह Http404 बढ़ाता है।

दर्शन

हम स्वचालित रूप से ObjectDoesNotExist अपवादों को एक उच्च स्तर पर पकड़ने के बजाय एक सहायक फ़ंक्शन get_object_or_404() उपयोग क्यों करते हैं, या ObjectDoesNotExist बजाय मॉडल API Http404 ?

क्योंकि यह मॉडल परत को दृश्य परत में जोड़ेगा। Django के सबसे महत्वपूर्ण डिजाइन लक्ष्यों में से एक ढीली युग्मन बनाए रखना है। कुछ नियंत्रित युग्मन django.shortcuts मॉड्यूल में पेश किए गए हैं।

एक get_object_or_404() get_list_or_404() फ़ंक्शन भी है, जो get_object_or_404() - के रूप में काम करता है - इसके अलावा filter() बजाय filter() का उपयोग करें। सूची खाली होने पर यह Http404 बढ़ाता है।

टेम्प्लेट सिस्टम का उपयोग करें

हमारे पोल आवेदन के लिए detail() दृश्य पर वापस जाएं। संदर्भ चर के question को देखते हुए, यहाँ polls/detail.html क्या है।

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

टेम्प्लेट सिस्टम, चर विशेषताओं को एक्सेस करने के लिए डॉट लुकिंग सिंटैक्स का उपयोग करता है। {{ question.question_text }} के उदाहरण में, पहले Django ऑब्जेक्ट question पर एक शब्दकोश खोज करता है। इस मामले में, यह एक विशेषता देखने की कोशिश करता है - जो इस मामले में काम करता है। यदि विशेषता लुकअप विफल हो गया था, तो यह एक सूची-सूचकांक लुकअप की कोशिश की होगी।

मेथड-कॉलिंग {% for %} लूप में होती है: question.choice_set.all की व्याख्या पायथन कोड question.choice_set.all() , जो Choice ऑब्जेक्ट्स के चलने योग्य रिटर्न देता है और {% for %} में उपयोग के लिए उपयुक्त है {% for %} टैग।

टेम्प्लेट के बारे में अधिक जानकारी के लिए टेम्प्लेट गाइड देखें।

टेम्प्लेट में हार्डकोड URL को हटाना

याद रखें, जब हमने किसी प्रश्न का लिंक polls/index.html टेम्पलेट में लिखा था, तो लिंक इस तरह आंशिक रूप से हार्डकोड किया गया था:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

इस हार्डकोड, कसकर युग्मित दृष्टिकोण के साथ समस्या यह है कि बहुत सारे टेम्प्लेट वाले प्रोजेक्ट्स पर URL को बदलना चुनौतीपूर्ण हो जाता है। हालाँकि, जब से आप polls.urls मॉड्यूल में path() फ़ंक्शन में नाम तर्क को परिभाषित करते हैं, आप {% url %} टेम्पलेट टैग का उपयोग करके अपने url कॉन्फ़िगरेशन में परिभाषित विशिष्ट URL पथों पर निर्भरता को हटा सकते हैं:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

जिस तरह से यह काम करता है, वह polls.urls में निर्दिष्ट परिभाषा के अनुसार URL परिभाषा को polls.urls है। आप यह देख सकते हैं कि नीचे 'विवरण' का URL नाम कहाँ परिभाषित किया गया है:

...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...

यदि आप चुनाव विवरण के URL को किसी अन्य चीज़ में बदलना चाहते हैं, तो शायद polls/specifics/12/ जैसी कुछ चीज़ों को टेम्पलेट (या टेम्प्लेट) में करने के बजाय आप इसे polls/urls.py में बदल देंगे:

...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...

नाम URL नामकरण

ट्यूटोरियल प्रोजेक्ट में सिर्फ एक ऐप है, polls । वास्तविक Django परियोजनाओं में, पांच, दस, बीस एप्लिकेशन या अधिक हो सकते हैं। Django उन दोनों के बीच URL नामों को कैसे अलग करता है? उदाहरण के लिए, polls ऐप में एक detail दृश्य होता है, और इसलिए उसी प्रोजेक्ट पर एक ऐप हो सकता है जो ब्लॉग के लिए है। कोई इसे कैसे बनाता है ताकि Django को पता हो कि {% url %} टेम्पलेट टैग का उपयोग करते समय एक url के लिए कौन सा ऐप देखना है?

इसका उत्तर आपके URLconf में नाम स्थान जोड़ने के लिए है। polls/urls.py फ़ाइल में, आगे बढ़ें और एप्लिकेशन नामस्थान सेट करने के लिए एक app_name जोड़ें:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

अब अपना polls/index.html टेम्पलेट बदलें:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

नाम विस्‍तारित विवरण को देखने के लिए:

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

जब आप लेखन विचारों के साथ सहज हों, तो सरल फ़ॉर्म प्रसंस्करण और सामान्य विचारों के बारे में जानने के लिए इस ट्यूटोरियल के भाग 4 को पढ़ें।