W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
表單處理通常有3個途徑:
自己實現(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
?。form_valid()
? 簡單重定向至 ?success_url
?。通用視圖在模型一起工作時真的很贊。這些通用視圖將自動創(chuàng)建 ?ModelForm
?,只要他們能找出要使用的模型類:
model
?屬性,則使用這個模型類。get_object()
? 返回一個對象,則使用這個對象的類。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
?。
若要跟蹤使用 ?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()
? 里處理未授權的用戶。
下面是一個展示了如何實現(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']
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: