Django 2.1.3 视图层 使用CBV进行表单处理

目录

  • 1. 基本的表单
  • 2. ModelForm
  • 3. 模型和request.user
  • 4. AJAX示例

内置CBV视图 | 总目录 | 使用mixins


表单处理通常有3种情况:

  • 初始 GET(空白或预填充式)
  • 使用无效数据进行POST(通常在错误之后重新显示表单)
  • 使用有效数据POST(处理数据并通常重定向)
    自己实现这个通常会导致很多重复的样板代码(请参阅在视图中使用表单)。为了避免这种情况,Django为表单处理提供了一组基于类的通用视图。

1. 基本的表单

给出一个简单的表单:

#forms.py 
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视图:

# views.py 
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)

注意:
1 . FormView继承自 TemplateResponseMixin,所以可以在这里使用 template_name 。
2.form_valid()的默认实现就是简单重定向到success_url。

译者注
html中这么使用:

<form action="{% url 'polls:cbv_form_view' %}" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.name.label }}{{ form.name }}<br>
        {{ form.message.label }}{{ form.message }}<br>
        <input type="submit" value="提交">
    form>

2. ModelForm

通用视图和model一起工作很屌。这些通用视图将自动创建一个ModelForm,只要它们可以确定要使用的模型类,可以通过以下三种方式:

  • 如果给出model属性,则将使用该模型类。
  • 如果get_object() 返回一个对象,则将使用该对象的类。
  • 如果给出了一个queryset,则将使用该查询集的模型。

ModelForm视图中form_valid()的实现是自动保存模型。如果您有任何特殊要求,可以覆盖它; 见下面的例子。

您甚至不需要为 CreateView 或 UpdateView 提供success_url - 如果get_absolute_url()可用,它们将在模型对象上使用此方法。

如果要使用自定义ModelForm(例如添加额外验证),只需在视图上设置 form_class即可 。

注意
指定自定义表单类时,您仍必须指定模型,即使 form_class 可能是个 ModelForm。

首先我们需要添加get_absolute_url()到我们的 Author类:

#models.py
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):
    	#译者注:这里author-detail应该是这种形式-> yourapp:author-detail  否则反向解析会报错
        return reverse('author-detail', kwargs={'pk': self.pk})

请注意我们如何在这里配置CBV的通用视图,我们自己不必写任何逻辑:

#views.py 

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
    #译者注:这里author-list应该是这种形式-> yourapp:author-list  否则反向解析会报错
    success_url = reverse_lazy('author-list')

注意
我们必须在这里使用 reverse_lazy(),而不是 reverse(),因为在导入文件时未加载URL。

fields属性的工作方式与ModelForm内部Meta类上的fields属性相同。除非您以另一种方式(通过指定form_class)定义表单类,否则该属性是必需的,如果不是,则视图将引发异常 ImproperlyConfigured。

如果同时指定 fields 和 form_class 属性, 则会引发异常ImproperlyConfigured。

最后,我们将这些新视图关联到URLconf:

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

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

注意

这些视图继承自 SingleObjectTemplateResponseMixin 它使用 template_name_suffix 构建 template_name 基于模型。

在这个例子中:

  • CreateView 和 UpdateView使用myapp/author_form.html(可以改变模板名,可以 在视图类中设置 template_name或 template_name_suffix)
  • DeleteView 使用 myapp/author_confirm_delete.html译者注:不可以改变模板名,只能是模型_confirm_delete.html

3. 模型和request.user

要跟踪用户使用CreateView创建的对象,可以使用自定义ModelForm来执行此操作。首先,将外键关系添加到模型中:

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

    # ...

在视图中,确保您没有在要fields列表中包含created_by字段,并覆盖 form_valid() 以添加用户:

# views.py 
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()中处理未经授权的用户 。

4. 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']

你可能感兴趣的:(Django,2.1,翻译)