Django基于类的编辑视图和Mixins

来源:互联网 发布:imovie windows 编辑:程序博客网 时间:2024/06/11 13:47
== 内建的基于类的通用编辑视图 (Forms)

表单(处理)通常包含3条路径:
* 初始的GET (空或预填充的表单)
* 非法数据的POST (通常重新显示表单并提示错误)
* 合法数据的POST (处理数据并通常重定向)

你自己实现这些常常需要重复很多模式化的代码。帮助避免这些,Django提供了一系列通用的基于类的视图用于表单处理。

- 基本表单

# 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

# 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):
        # 当合法form数据被POST时,此方法被调用。
        # 它应当返回一个HttpResponse.
        form.send_email()
        return super(ContactView, self).form_valid(form)

- Model表单

通用视图将自动创建ModelForm, 依据下列规则:
* 如果给出model属性,其model类将被使用
* 如果get_object()返回一个对象,此对象的类被使用
* 如果给出queryset,则queryset的model被使用

Model form视图提供了一个form_valid()实现,自动保存model对象。你可以根据自己的需要重写它。

对于CreateView或UpdateView,你甚至不需要提供一个success_url, 它们将使用model对象的get_absolute_url(),如果可用。

如果你需要自定义ModelForm(例如,增加校验),只需要在你的视图(view)中设置form_class, *还必须设置model.

# models.py
from django.core.urlresolvers 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})

# views.py
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers 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')

# urls.py
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 和 request.user

为跟踪使用CreateView创建某对象的用户,你可以自定义一个ModelForm.

# models.py
class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User)

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

- AJAX 用例

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

class AjaxableResponseMixin(object):
    """
Mixin用于为form增加AJAX支持。
必须用于基于类的FormView(如,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):
# 我们需要确保调用父类的form_valid()方法,因为它可能会做一些处理
# (在CreateView的例子中,它将调用form.save())
        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']


== 在基于类的视图中使用Mixins
https://docs.djangoproject.com/en/1.8/ref/class-based-views/mixins/

- 内容及模板响应
TemplateResponseMixin
ContextMixin

- 构建Django的通用基于类的视图
DetailView: working with a single Django object
#To get the object, DetailView relies on SingleObjectMixin
#To then make a TemplateResponse, DetailView uses SingleObjectTemplateResponseMixin

ListView: working with many Django objects
#To get the objects, ListView uses MultipleObjectMixin
#To make a TemplateResponse, ListView then uses MultipleObjectTemplateResponseMixin

- 使用Django的基于类视图的Mixins
Using SingleObjectMixin with View
Using SingleObjectMixin with ListView

- 避免更复杂
Using FormMixin with DetailView
A better solution
An alternative better solution

- 不限于HTML

from django.http import JsonResponse

class JSONResponseMixin(object):
    """
    A mixin that can be used to render a JSON response.
    """
    def render_to_json_response(self, context, **response_kwargs):
        """
        Returns a JSON response, transforming 'context' to make the payload.
        """
        return JsonResponse(
            self.get_data(context),
            **response_kwargs
        )

    def get_data(self, context):
        """
        Returns an object that will be serialized as JSON by json.dumps().
        """
        # Note: This is *EXTREMELY* naive; in reality, you'll need
        # to do much more complex handling to ensure that arbitrary
        # objects -- such as Django model instances or querysets
        # -- can be serialized as JSON.
        return context

from django.views.generic import TemplateView

class JSONView(JSONResponseMixin, TemplateView):
    def render_to_response(self, context, **response_kwargs):

        return self.render_to_json_response(context, **response_kwargs)


0 0
原创粉丝点击