Django4.0 基于類的視圖-使用基于類的視圖處理表單

2022-03-16 17:57 更新

表單處理通常有3個途徑:

  • 初始 GET (空白或預填充表單)
  • 帶有合法數(shù)據(jù)的POST(通常是帶有錯誤的重新顯示的表單)
  • 帶有合法數(shù)據(jù)的POST(處理數(shù)據(jù)和通常重定向)

自己實現(xiàn)這個會導致很多重復的樣板代碼。為了避免這個問題,Django 提供了一組通用基于類的視圖來處理表單。

基礎表單

提供聯(lián)系表單:

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 ContactFormView(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 ?。
  • 默認實現(xiàn)了 ?form_valid()?  簡單重定向至 ?success_url ?。

模型表單

通用視圖在模型一起工作時真的很贊。這些通用視圖將自動創(chuàng)建 ?ModelForm ?,只要他們能找出要使用的模型類:

  • 如果已經(jīng)給出了 ?model ?屬性,則使用這個模型類。
  • 如果 ?get_object()? 返回一個對象,則使用這個對象的類。
  • 如果已經(jīng)給出了 ?queryset  ?,則使用這個查詢集的模型。

模型表單視圖提供一個 ?form_valid()? 實現(xiàn),來自動保存模型。如果你有特別的需求,你可以覆蓋它。
你甚至不需要為 ?CreateView ?或 ?UpdateView ?提供 ?success_url ?。如果可用,它們將在模型對象上使用 ?get_absolute_url()? 。
如果你想使用一個自定義的 ?ModelForm ?(比如添加額外的驗證),用來在視圖上設置 ?form_class ?。

注解:當指定一個自定義表單類時,必須也要指定模型,即使 ?form_class ?可能是一個 ?ModelForm ?。

首先我們需要添加 ?get_absolute_url()? 到 ?Author ?類:

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 ?并友好的執(zhí)行實際工作。注意這里我們?nèi)绾闻渲猛ㄓ没陬惖囊晥D。我們不用自己編寫任何邏輯:

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

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

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

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

注解:我們必須在這里使用 ?reverse_lazy()? 來代替 ?reverse()? ,因為在文件導入時不加載 ?urls ?。

?fields ?屬性的工作方式同 ?ModelForm ?中內(nèi)部 ?Meta ?類的 ?fields ?屬性一樣。除非你使用其他方式定義表單類,該屬性是必需的,如果屬性不存在,視圖將引發(fā) ?ImproperlyConfigured ?異常。
如果同時指定了 ?fields ?和 ?form_class ?屬性,將會引發(fā) ?ImproperlyConfigured ?異常。
最后將這些新視圖掛鉤到?URLconf?中:

from django.urls import path
from myapp.views import AuthorCreateView, AuthorDeleteView, AuthorUpdateView

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

注解:這些視圖繼承 ?SingleObjectTemplateResponseMixin ?,它使用 ?template_name_suffix ?來構建基于模型的 ?template_name ?。在這個例子里:

  • ?CreateView ?和 ?UpdateView ?使用 ?myapp/author_form.html? 。
  • ?DeleteView ?使用 ?myapp/author_confirm_delete.html? 。

如果你想為 ?CreateView ?和 ?UpdateView ?制作單獨的模板,你可以在視圖類上設置 ?template_name ?或 ?template_name_suffix ?。

模型和 request.user

若要跟蹤使用 ?CreateView ?創(chuàng)建的用戶,你可以使用自定義的 ?ModelForm ?來執(zhí)行此操作。首先,在模型里添加外鍵關系:

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.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreateView(LoginRequiredMixin, CreateView):
    model = Author
    fields = ['name']

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

?LoginRequiredMixin ?防止那些未登錄的用戶訪問表單。如果忽略,那么你將需要在 ?form_valid()? 里處理未授權的用戶。

內(nèi)容協(xié)商示例

下面是一個展示了如何實現(xiàn)基于API的工作流以及普通?POST?表單一起使用的表單:

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

class JsonableResponseMixin:
    """
    Mixin to add JSON 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.accepts('text/html'):
            return response
        else:
            return JsonResponse(form.errors, status=400)

    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.accepts('text/html'):
            return response
        else:
            data = {
                'pk': self.object.pk,
            }
            return JsonResponse(data)

class AuthorCreateView(JsonableResponseMixin, CreateView):
    model = Author
    fields = ['name']


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號