Django 2.1 - Form handling with class-based views

क्लास-आधारित विचारों के साथ फॉर्म हैंडलिंग




django

क्लास-आधारित विचारों के साथ फॉर्म हैंडलिंग

फॉर्म प्रोसेसिंग में आम तौर पर 3 रास्ते होते हैं:

  • प्रारंभिक GET (रिक्त या पूर्वनिर्मित रूप)
  • अमान्य डेटा के साथ POST (आमतौर पर त्रुटियों के साथ फिर से तैयार करना)
  • वैध डेटा के साथ पोस्ट (डेटा की प्रक्रिया और आम तौर पर पुनर्निर्देशित)

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

मूल रूप

एक सरल संपर्क फ़ॉर्म दिया गया:

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    message = forms.CharField(widget=forms.Textarea)

    def send_email(self):
        # send email using the self.cleaned_data dictionary
        pass

FormView व्यू का उपयोग कर निर्माण किया जा सकता है:

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        form.send_email()
        return super().form_valid(form)

टिप्पणियाँ:

  • FormView इनहेरिट किया गया TemplateResponseMixin इसलिए template_name का उपयोग यहां किया जा सकता है।
  • form_valid() लिए डिफ़ॉल्ट कार्यान्वयन केवल success_url पुनर्निर्देशित करता है।

मॉडल रूपों

मॉडल के साथ काम करते समय सामान्य दृश्य वास्तव में चमकते हैं। ये सामान्य विचार स्वचालित रूप से एक ModelForm बनाएंगे, जब तक कि वे किस मॉडल वर्ग का उपयोग करने के लिए काम कर सकते हैं:

  • यदि model विशेषता दी जाती है, तो उस मॉडल वर्ग का उपयोग किया जाएगा।
  • यदि get_object() किसी ऑब्जेक्ट को लौटाता है, तो उस ऑब्जेक्ट के वर्ग का उपयोग किया जाएगा।
  • यदि कोई queryset दी गई है, तो उस क्वेरीसेट के लिए मॉडल का उपयोग किया जाएगा।

मॉडल प्रपत्र दृश्य एक form_valid() कार्यान्वयन प्रदान करते हैं जो मॉडल को स्वचालित रूप से सहेजता है। यदि आपकी कोई विशेष आवश्यकता है तो आप इसे ओवरराइड कर सकते हैं; उदाहरण के लिए नीचे देखें।

आपको CreateView या success_url लिए एक success_url प्रदान करने की भी आवश्यकता नहीं है - यदि वे उपलब्ध हो तो मॉडल ऑब्जेक्ट पर get_absolute_url() उपयोग करेंगे।

यदि आप एक कस्टम ModelForm (उदाहरण के लिए अतिरिक्त सत्यापन जोड़ने के लिए) का उपयोग करना चाहते हैं, तो बस अपने विचार पर form_class सेट करें।

ध्यान दें

कस्टम प्रपत्र वर्ग निर्दिष्ट करते समय, आपको अभी भी मॉडल निर्दिष्ट करना होगा, भले ही form_class एक form_class हो सकता है।

पहले हमें अपने Author वर्ग में get_absolute_url() जोड़ना get_absolute_url() :

from django.db import models
from django.urls import reverse

class Author(models.Model):
    name = models.CharField(max_length=200)

    def get_absolute_url(self):
        return reverse('author-detail', kwargs={'pk': self.pk})

फिर हम वास्तविक कार्य करने के लिए CreateView और दोस्तों का उपयोग कर सकते हैं। ध्यान दें कि हम यहां केवल सामान्य वर्ग-आधारित विचारों को कैसे कॉन्फ़िगर कर रहे हैं; हमें स्वयं कोई तर्क नहीं लिखना है:

from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name']

class AuthorUpdate(UpdateView):
    model = Author
    fields = ['name']

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

ध्यान दें

हमें यहाँ reverse_lazy() का उपयोग करना है, न कि reverse() रूप में जब फ़ाइल आयात किया जाता है तो url लोड नहीं होता है।

fields विशेषता उसी तरह से काम करती है जिस तरह से ModelForm पर आंतरिक Meta क्लास पर fields विशेषता होती है। जब तक आप फॉर्म क्लास को किसी अन्य तरीके से परिभाषित नहीं करते हैं, तब तक विशेषता की आवश्यकता होती है और दृश्य एक ImproperlyConfigured अपवाद को बढ़ाएगा यदि नहीं।

यदि आप दोनों fields और form_class विशेषताएँ निर्दिष्ट करते हैं, तो एक form_class अपवाद उठाया जाएगा।

अंत में, हम URLconf में इन नए विचारों को हुक करते हैं:

from django.urls import path
from myapp.views import AuthorCreate, AuthorDelete, AuthorUpdate

urlpatterns = [
    # ...
    path('author/add/', AuthorCreate.as_view(), name='author-add'),
    path('author/<int:pk>/', AuthorUpdate.as_view(), name='author-update'),
    path('author/<int:pk>/delete/', AuthorDelete.as_view(), name='author-delete'),
]

ध्यान दें

ये विचार SingleObjectTemplateResponseMixin इनहेरिट SingleObjectTemplateResponseMixin जो मॉडल पर आधारित template_name_suffix के निर्माण के लिए template_name का उपयोग करता है।

इस उदाहरण में:

यदि आप CreateView और UpdateView लिए अलग टेम्प्लेट की इच्छा रखते हैं, तो आप अपने व्यू क्लास पर template_name या template_name_suffix सेट कर सकते हैं।

मॉडल और request.user

CreateView का उपयोग करके ऑब्जेक्ट बनाने वाले उपयोगकर्ता को ट्रैक करने के लिए, आप ऐसा करने के लिए एक कस्टम ModelForm का उपयोग कर सकते हैं। सबसे पहले, मॉडल में विदेशी कुंजी संबंध जोड़ें:

from django.contrib.auth.models import User
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    # ...

दृश्य में, सुनिश्चित करें कि आपने फ़ील्ड को संपादित करने के लिए created_by को शामिल नहीं किया है और उपयोगकर्ता को जोड़ने के लिए form_valid() को ओवरराइड करें:

from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name']

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super().form_valid(form)

ध्यान दें कि आपको इस दृश्य को login_required() , या वैकल्पिक रूप से अनधिकृत उपयोगकर्ताओं को form_valid() का उपयोग करके सजाने की आवश्यकता होगी।

AJAX का उदाहरण

यहां एक सरल उदाहरण दिखाया गया है कि आप AJAX अनुरोधों के साथ-साथ 'सामान्य' फ़ॉर्म POST के लिए काम करने वाले फ़ॉर्म को लागू करने के बारे में कैसे जा सकते हैं:

from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

class AjaxableResponseMixin:
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def form_invalid(self, form):
        response = super().form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        # We make sure to call the parent's form_valid() method because
        # it might do some processing (in the case of CreateView, it will
        # call form.save() for example).
        response = super().form_valid(form)
        if self.request.is_ajax():
            data = {
                'pk': self.object.pk,
            }
            return JsonResponse(data)
        else:
            return response

class AuthorCreate(AjaxableResponseMixin, CreateView):
    model = Author
    fields = ['name']