Menangani formulir dengan tampilan berdasarkan-kelasLink to this heading

Pengolahan formulir umumnya mempunyai 3 jalur:

  • Inisial GET (kosong atau formulir diisi dimuka)

  • POST dengan data tidak sah (khususnya memperlihatkan kembali formulir dengan kesalahan)

  • POST dengan data sah (pengolahan data dan khususnya pengalihan)

Menerapkan ini anda sendiri sering menghasilkan banyak perulangan kode boilerplate (lihat Using a form in a view). Untuk menghindai ini, Django menyediakan kumpulan dari tampilan berdasarkan-kelas umum untuk pengolahan formulir.

Formulir dasarLink to this heading

Diberikan formulir kontak sederhana:

forms.py
Code
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

Tampilan dapat dibangun menggunakan FormView:

views.py
Code
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(ContactView, self).form_valid(form)

Catatan:

Formulir modelLink to this heading

Tampilan umum bersinar ketika bekerja dengan model. Tampilan umum ini akan secara otomatis membuat sebuah ModelForm, selama mereka dapat bekerya kelas model mana digunakan:

  • Jika atribut model diberikan, kelas model itu akan digunakan.

  • Jika get_object() mengembalikan sebuah obyek, kelas dari obyek akan digunakan.

  • Jika sebuah queryset diberikan, model untuk queryset itu akan digunakan.

Tampilan formulir model menyediakan sebuah penerapan form_valid() yang menyimpan model secara otomatis. Anda dapat menimpa ini jika anda mempunyai persyaratan khusus lainnya; lihat dibawah untuk contoh.

Anda tidak perlu menyediakan sebuah success_url untuk CreateView atau UpdateView - mereka akan menggunakan get_absolute_url() pada obyek model jika tersedia.

Jika anda ingin menggunakan penyesuaian ModelForm (sebagai contoh untuk menambah pengesahan tambahan) cukup setel form_class pada tampilan anda.

Pertama kami butuh menambahkan get_absolute_url() ke kelas Author kami:

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

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

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

Kemudian kami dapat menggunakan CreateView dan teman-teman untuk melakukan pekerjaan sebenarnya. Perhatikan bagaimana kami hanya mengkonfigurasi tampilan berdasarkan-kelas umum disini; kami tidak harus menulis logika apapun kami sendiri:

views.py
Code
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
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')

Atribut fields bekerja cara sama seperti atribut fields pada kelas Meta sebelah dalam pada ModelForm. Meskipun anda menentukan kelas formulir di cara lain, atribut dibutuhkan dan tampilan akan munculkan sebuah pengecualian ImproperlyConfigured jika itu tidak.

Jika anda menentukan kedua atribut fields dan form_class, sebuah pengecualian ImproperlyConfigured akan dimunculkan.

Akhirnya, kami mengaitkan tampilan baru ini kedalam URLconf:

urls.py
Code
from django.conf.urls import url
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete

urlpatterns = [
    # ...
    url(r'author/add/$', AuthorCreate.as_view(), name='author-add'),
    url(r'author/(?P<pk>[0-9]+)/$', AuthorUpdate.as_view(), name='author-update'),
    url(r'author/(?P<pk>[0-9]+)/delete/$', AuthorDelete.as_view(), name='author-delete'),
]

Models dan request.userLink to this heading

Untuk melacak pengguna yang membuat sebuah obyek menggunakan sebuah CreateView, anda dapat menggunakan sebuah penyesuaian ModelForm untuk melakukan ini. Pertama, tambah hubungan foreign key pada model:

models.py
Code
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)

    # ...

Di tampilan, pastikan bahwa anda tidak menyertakan created_by di daftar dari bidang untuk menyunting, dan menimpa form_valid() untuk menambah pengguna:

views.py
Code
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(AuthorCreate, self).form_valid(form)

Catata bahwa anda akan butuh decorate this view menggunakan login_required(), atau cara lain menangani pengguna tidak berhak di form_valid().

Contoh AJAXLink to this heading

Ini adalah contoh sederhana menunjukkan bagaimana anda mungkin pergi tentang menerapkan sebuah formulir yang bekerja untuk permintaan AJAX sama seperti formulir POST 'normal':

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

class AjaxableResponseMixin(object):
    """
    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(AjaxableResponseMixin, self).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(AjaxableResponseMixin, self).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']