Django 2.1 - Writing your first Django app, part 7

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




django

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

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

व्यवस्थापक फ़ॉर्म को कस्टमाइज़ करें

admin.site.register(Question) साथ Question मॉडल को पंजीकृत करके, Django एक डिफ़ॉल्ट फॉर्म प्रतिनिधित्व का निर्माण करने में सक्षम था। अक्सर, आप कस्टमाइज़ करना चाहते हैं कि व्यवस्थापक फ़ॉर्म कैसा दिखता है और काम करता है। जब आप ऑब्जेक्ट को पंजीकृत करते हैं तो आप Django को उन विकल्पों के बारे में बताएंगे जो आप चाहते हैं।

आइए देखें कि यह कैसे संपादित फ़ॉर्म पर फ़ील्ड्स को पुन: व्यवस्थित करके काम करता है। इसके साथ admin.site.register(Question) लाइन बदलें:

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question_text']

admin.site.register(Question, QuestionAdmin)

आप इस पैटर्न का पालन करेंगे - एक मॉडल व्यवस्थापक वर्ग बनाएँ, फिर इसे व्यवस्थापन के दूसरे तर्क के रूप में पास करें। admin.site.register() - किसी भी समय आपको किसी मॉडल के लिए व्यवस्थापक विकल्प बदलने की आवश्यकता होती है।

उपरोक्त विशेष परिवर्तन "प्रकाशन दिनांक" "प्रश्न" फ़ील्ड से पहले आता है:

फ़ील्ड्स को फिर से व्यवस्थित किया गया है

यह केवल दो क्षेत्रों के साथ प्रभावशाली नहीं है, लेकिन दर्जनों फ़ील्ड्स के साथ व्यवस्थापन प्रपत्रों के लिए, एक सहज ज्ञान युक्त ऑर्डर चुनना एक महत्वपूर्ण प्रयोज्य विवरण है।

और दर्जनों फ़ील्ड्स के साथ फ़ॉर्म की बात करते हुए, आप फ़ॉर्म को फ़ील्ड्स में विभाजित करना चाहते हैं:

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Question, QuestionAdmin)

फ़ील्डसेट में प्रत्येक टपल का पहला तत्व fieldsets का शीर्षक है। यहाँ हमारा रूप अब जैसा दिखता है:

फॉर्म में अब फील्डसेट हैं

फिर भी।

इस समस्या को हल करने के दो तरीके हैं। पहला Question साथ Choice रजिस्टर करने का है जैसा कि हमने Question साथ किया था। यह आसान है:

from django.contrib import admin

from .models import Choice, Question
# ...
admin.site.register(Choice)

अब "विकल्प" Django व्यवस्थापक में एक उपलब्ध विकल्प है। "पसंद जोड़ें" फ़ॉर्म इस तरह दिखता है:

चॉइस एडमिन पेज

उस रूप में, "प्रश्न" फ़ील्ड एक चयनित बॉक्स है जिसमें डेटाबेस का प्रत्येक प्रश्न होता है। Django जानता है कि एक ForeignKey को व्यवस्थापक में <select> बॉक्स के रूप में प्रतिनिधित्व किया जाना चाहिए। हमारे मामले में, इस बिंदु पर केवल एक प्रश्न मौजूद है।

"प्रश्न" के आगे "एक और जोड़ें" लिंक पर भी ध्यान दें। दूसरे के लिए एक ForeignKey संबंध के साथ प्रत्येक वस्तु मुफ्त में मिलती है। जब आप "एक और जोड़ें" पर क्लिक करते हैं, तो आपको "प्रश्न जोड़ें" फ़ॉर्म के साथ एक पॉपअप विंडो मिलेगी। यदि आप उस विंडो में एक प्रश्न जोड़ते हैं और "सहेजें" पर क्लिक करते हैं, तो Django डेटाबेस में सवाल को बचाएगा और गतिशील रूप से इसे "पसंद जोड़ें" फ़ॉर्म पर चयनित विकल्प के रूप में जोड़ देगा।

लेकिन, वास्तव में, यह सिस्टम में Choice ऑब्जेक्ट्स को जोड़ने का एक अक्षम तरीका है। यदि आप Question ऑब्जेक्ट बनाते समय सीधे विकल्पों का एक समूह जोड़ सकते हैं तो बेहतर होगा। आइए बनाते हैं।

Choice मॉडल के लिए register() कॉल निकालें। फिर, पढ़ने के लिए Question पंजीकरण कोड को संपादित करें:

from django.contrib import admin

from .models import Choice, Question


class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

यह Django को बताता है: “ Choice ऑब्जेक्ट्स को Question व्यवस्थापक पृष्ठ पर संपादित किया जाता है। डिफ़ॉल्ट रूप से, 3 विकल्पों के लिए पर्याप्त फ़ील्ड प्रदान करें। "

"प्रश्न जोड़ें" पृष्ठ को लोड करें यह देखने के लिए कि कैसा दिखता है:

प्रश्न पृष्ठ जोड़ें अब इस पर विकल्प हैं

यह इस तरह से काम करता है: संबंधित विकल्पों के लिए तीन स्लॉट हैं - जैसा कि extra द्वारा निर्दिष्ट किया गया है - और हर बार जब आप पहले से निर्मित ऑब्जेक्ट के लिए "बदलें" पृष्ठ पर वापस आते हैं, तो आपको एक और तीन अतिरिक्त स्लॉट मिलते हैं।

तीन वर्तमान स्लॉट्स के अंत में आपको "एक और विकल्प जोड़ें" लिंक मिलेगा। यदि आप उस पर क्लिक करते हैं, तो एक नया स्लॉट जोड़ा जाएगा। यदि आप जोड़े गए स्लॉट को हटाना चाहते हैं, तो आप एक्स पर जोड़े गए स्लॉट के शीर्ष दाईं ओर क्लिक कर सकते हैं। ध्यान दें कि आप मूल तीन स्लॉट नहीं निकाल सकते। यह चित्र एक जोड़ा स्लॉट दिखाता है:

अतिरिक्त स्लॉट गतिशील रूप से जोड़ा गया

एक छोटी सी समस्या, हालांकि। संबंधित Choice ऑब्जेक्ट में प्रवेश करने के लिए सभी क्षेत्रों को प्रदर्शित करने के लिए बहुत सारे स्क्रीन स्पेस चाहिए। उस कारण से, Django इनलाइन संबंधित वस्तुओं को प्रदर्शित करने का एक सारणीबद्ध तरीका प्रदान करता है; आपको बस पढ़ने के लिए ChoiceInline घोषणा को बदलने की आवश्यकता है:

class ChoiceInline(admin.TabularInline):
    #...

उस TabularInline ( TabularInline बजाय) के साथ, संबंधित ऑब्जेक्ट अधिक कॉम्पैक्ट, टेबल-आधारित प्रारूप में प्रदर्शित होते हैं:

प्रश्न पृष्ठ जोड़ें अब अधिक कॉम्पैक्ट विकल्प हैं

ध्यान दें कि एक अतिरिक्त "हटाएं?" कॉलम है जो "एक और विकल्प जोड़ें" बटन का उपयोग करके पंक्तियों को हटाने की अनुमति देता है और उन पंक्तियों को जो पहले से ही सहेजे गए हैं।

व्यवस्थापक परिवर्तन सूची अनुकूलित करें

अब जबकि प्रश्न व्यवस्थापक पृष्ठ अच्छा लग रहा है, तो "परिवर्तन सूची" पृष्ठ पर कुछ ट्विक्स करें - वह जो सिस्टम के सभी प्रश्नों को प्रदर्शित करता है।

इस बिंदु पर यह कैसा दिखता है:

पोल सूची पृष्ठ को बदलते हैं

डिफ़ॉल्ट रूप से, Django प्रत्येक ऑब्जेक्ट के str() को प्रदर्शित करता है। लेकिन कभी-कभी यह अधिक उपयोगी होगा यदि हम व्यक्तिगत क्षेत्रों को प्रदर्शित कर सकते हैं। ऐसा करने के लिए, list_display व्यवस्थापक विकल्प का उपयोग करें, जो ऑब्जेक्ट के लिए परिवर्तन सूची पृष्ठ पर कॉलम के रूप में प्रदर्शित करने के लिए फ़ील्ड नामों का एक समूह है:

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date')

बस अच्छे उपाय के लिए, आइए ट्यूटोरियल 2 से was_published_recently() विधि भी शामिल करें:

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date', 'was_published_recently')

अब प्रश्न परिवर्तन सूची पृष्ठ इस तरह दिखता है:

पोल सूची पृष्ठ बदल दिया, अद्यतन

आप उन मानों के आधार पर सॉर्ट करने के लिए कॉलम हेडर पर क्लिक कर सकते हैं - was_published_recently हेडर के मामले को छोड़कर, क्योंकि एक मनमाने तरीके के आउटपुट द्वारा सॉर्टिंग समर्थित नहीं है। यह भी ध्यान दें कि was_published_recently लिए कॉलम हेडर, डिफ़ॉल्ट रूप से, विधि का नाम (अंडरस्कोर के साथ रिक्त स्थान के साथ बदल दिया गया है) और प्रत्येक पंक्ति में आउटपुट का स्ट्रिंग प्रतिनिधित्व होता है।

आप कुछ तरीकों से इस पद्धति ( polls/models.py ) को दे कर इसमें सुधार कर सकते हैं:

class Question(models.Model):
    # ...
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

इन विधि गुणों के बारे में अधिक जानकारी के लिए, देखें list_display

अपने polls/admin.py फ़ाइल को फिर से संपादित करें और Question परिवर्तन सूची पृष्ठ में सुधार जोड़ें: list_filter का उपयोग करके फ़िल्टर करें। QuestionAdmin लिए निम्नलिखित पंक्ति जोड़ें:

list_filter = ['pub_date']

यह एक "फ़िल्टर" साइडबार जोड़ता है जो लोगों को pub_date फ़ील्ड द्वारा परिवर्तन सूची को फ़िल्टर करने देता है:

पोल सूची पृष्ठ बदल दिया, अद्यतन

प्रदर्शित फिल्टर का प्रकार उस क्षेत्र के प्रकार पर निर्भर करता है जिस पर आप फ़िल्टर कर रहे हैं। क्योंकि pub_date एक DateTimeField , इसलिए Django उपयुक्त फ़िल्टर विकल्प देना जानता है: "कोई भी तारीख", "आज", "पिछला 7 दिन", "यह महीना", "इस वर्ष"।

यह अच्छी तरह से आकार ले रहा है। आइए कुछ खोज क्षमता जोड़ें:

search_fields = ['question_text']

यह परिवर्तन सूची के शीर्ष पर एक खोज बॉक्स जोड़ता है। जब कोई व्यक्ति खोज शब्द दर्ज करता है, तो Django प्रश्न_ क्षेत्र की खोज करेगा। आप जितने चाहें उतने फ़ील्ड का उपयोग कर सकते हैं - हालाँकि क्योंकि यह पर्दे के पीछे एक LIKE क्वेरी का उपयोग करता है, खोज फ़ील्ड की संख्या को एक उचित संख्या तक सीमित करने से आपके डेटाबेस के लिए खोज करना आसान हो जाएगा।

अब यह भी ध्यान देने के लिए एक अच्छा समय है कि परिवर्तन सूचियाँ आपको मुफ्त अंकुश देती हैं। डिफ़ॉल्ट प्रति पृष्ठ 100 आइटम प्रदर्शित करना है। Change list pagination , search boxes , list_filter , date-hierarchies , और list_display सभी एक साथ काम करते हैं जैसे आपको लगता है कि उन्हें चाहिए।

कस्टमाइज़ लुक और फील को कस्टमाइज़ करें

स्पष्ट रूप से, प्रत्येक व्यवस्थापक पृष्ठ के शीर्ष पर "Django प्रशासन" होना हास्यास्पद है। यह सिर्फ प्लेसहोल्डर टेक्स्ट है।

हालांकि, Django के टेम्प्लेट सिस्टम का उपयोग करके इसे बदलना आसान है। Django व्यवस्थापन Django द्वारा ही संचालित किया जाता है, और इसके इंटरफेस Django के अपने टेम्पलेट सिस्टम का उपयोग करते हैं।

अपनी परियोजना के खाके को अनुकूलित करना

अपने प्रोजेक्ट डायरेक्टरी में एक templates डायरेक्टरी बनाएं (जिसमें manage.py शामिल है)। टेम्पलेट आपके फ़ाइल सिस्टम पर कहीं भी रह सकते हैं जिसे Django एक्सेस कर सकता है। (Django अपने उपयोगकर्ता को चलाने वाले के रूप में चलाता है।) हालांकि, परियोजना के भीतर अपने टेम्पलेट को रखना एक अच्छा सम्मेलन है जिसका पालन करना है।

अपनी सेटिंग फ़ाइल खोलें ( mysite/settings.py , याद रखें) और DIRS सेटिंग में एक DIRS विकल्प जोड़ें:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Django टेम्प्लेट लोड करते समय जांचने के लिए DIRS फाइलसिस्टम निर्देशिकाओं की एक सूची है; यह एक खोज पथ है।

खाके का आयोजन

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

अब templates अंदर admin नामक एक निर्देशिका बनाएँ, और उस निर्देशिका में Django ही ( django/contrib/admin/templates ) के स्रोत कोड में डिफ़ॉल्ट Django व्यवस्थापक टेम्पलेट निर्देशिका के भीतर टेम्पलेट admin/base_site.html प्रतिलिपि बनाएँ।

Django स्रोत फ़ाइलें कहाँ हैं?

यदि आपको यह पता लगाने में कठिनाई होती है कि आपके सिस्टम पर Django स्रोत फ़ाइलें कहाँ स्थित हैं, तो निम्न कमांड चलाएँ:

$ python -c "import django; print(django.__path__)"
...\> py -c "import django; print(django.__path__)"

फिर, बस फ़ाइल को संपादित करें और {{ site_header|default:_('Django administration') }} प्रतिस्थापित करें (जैसे कि घुंघराले ब्रेसेस सहित) अपनी साइट के नाम के साथ जैसा कि आप फिट देखते हैं। आपको एक कोड के साथ अंत करना चाहिए जैसे:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

हम इस दृष्टिकोण का उपयोग आपको टेम्प्लेट को ओवरराइड करने के तरीके सिखाने के लिए करते हैं। एक वास्तविक परियोजना में, आप शायद django.contrib.admin.AdminSite.site_header विशेषता का उपयोग अधिक आसानी से इस विशेष अनुकूलन को करने के लिए करेंगे।

इस टेम्प्लेट फ़ाइल में बहुत सारे पाठ होते हैं जैसे {% block branding %} और {{ title }}{% और {{ टैग Django की टेम्पलेट भाषा का हिस्सा हैं। जब Django admin/base_site.html प्रस्तुत करता है, तो इस टेम्पलेट भाषा का मूल्यांकन अंतिम HTML पृष्ठ का उत्पादन करने के लिए किया जाएगा, जैसा कि हमने ट्यूटोरियल 3 में देखा था।

ध्यान दें कि Django के किसी भी डिफ़ॉल्ट व्यवस्थापक टेम्प्लेट को ओवरराइड किया जा सकता है। एक टेम्प्लेट को ओवरराइड करने के लिए, बस वही करें जो आपने base_site.html साथ किया था - इसे डिफ़ॉल्ट निर्देशिका से अपने कस्टम डायरेक्टरी में कॉपी करें, और बदलाव करें।

अपने एप्लिकेशन के टेम्प्लेट को अनुकूलित करना

DIRS पाठक पूछेंगे: लेकिन यदि DIRS डिफ़ॉल्ट रूप से खाली था, तो Django को डिफ़ॉल्ट व्यवस्थापक टेम्पलेट कैसे मिल रहा था? इसका उत्तर यह है कि, चूंकि APP_DIRS सही पर सेट है, Django स्वचालित रूप से प्रत्येक एप्लिकेशन पैकेज के भीतर templates/ उपनिर्देशिका की तलाश करता है, एक फ़ॉलबैक के रूप में उपयोग करने के लिए (यह मत भूलो कि django.contrib.admin एक एप्लिकेशन है)।

हमारा मतदान आवेदन बहुत जटिल नहीं है और इसके लिए कस्टम व्यवस्थापक टेम्पलेट की आवश्यकता नहीं है। लेकिन अगर यह अपनी कार्यक्षमता के लिए Django के मानक व्यवस्थापक टेम्पलेट्स के अधिक परिष्कृत और आवश्यक संशोधन को बढ़ाता है, तो यह प्रोजेक्ट में उन लोगों के बजाय एप्लिकेशन के टेम्पलेट्स को संशोधित करने के लिए अधिक समझदार होगा। इस तरह, आप किसी भी नई परियोजना में चुनावों के आवेदन को शामिल कर सकते हैं और यह आश्वस्त हो सकते हैं कि इसे आवश्यक कस्टम टेम्पलेट मिलेंगे।

Django अपने टेम्प्लेट को कैसे ढूँढता है, इसके बारे में अधिक जानकारी के लिए टेम्प्लेट लोडिंग दस्तावेज़ देखें।

व्यवस्थापक सूचकांक पृष्ठ को अनुकूलित करें

एक समान नोट पर, आप Django व्यवस्थापक इंडेक्स पेज के रूप और स्वरूप को अनुकूलित करना चाह सकते हैं।

डिफ़ॉल्ट रूप से, यह INSTALLED_APPS में उन सभी ऐप्स को प्रदर्शित करता है जिन्हें व्यवस्थापक एप्लिकेशन के साथ वर्णानुक्रम में पंजीकृत किया गया है। आप लेआउट में महत्वपूर्ण बदलाव करना चाहते हैं। आखिरकार, सूचकांक संभवतः व्यवस्थापक का सबसे महत्वपूर्ण पृष्ठ है, और इसका उपयोग करना आसान होना चाहिए।

अनुकूलित करने के लिए टेम्पलेट admin/index.html । (पिछले अनुभाग में admin/base_site.html साथ भी ऐसा ही करें - इसे डिफ़ॉल्ट निर्देशिका से अपने कस्टम टेम्पलेट निर्देशिका में कॉपी करें)। फ़ाइल को संपादित करें, और आप देखेंगे कि यह app_list नामक टेम्पलेट चर का उपयोग करता है। उस चर में हर स्थापित Django ऐप शामिल है। इसका उपयोग करने के बजाय, आप जो कुछ भी सोचते हैं, उसके अनुसार ऑब्जेक्ट-विशिष्ट व्यवस्थापक पृष्ठों के लिंक को हार्ड-कोड कर सकते हैं।

आगे क्या होगा?

शुरुआती ट्यूटोरियल यहां समाप्त होता है। इस बीच, आप कुछ संकेत की जाँच करना चाहेंगे कि यहाँ से कहाँ जाना है

यदि आप पायथन पैकेजिंग से परिचित हैं और "पुन: प्रयोज्य एप्लिकेशन" में मतदान कैसे करें, यह सीखने में रुचि रखते हैं, तो उन्नत ट्यूटोरियल देखें: पुन: प्रयोज्य एप्लिकेशन कैसे लिखें