• 用基于类的通用视图处理表单(Class-based generic views)


    处理表单通常包含3步:

    • 初始化GET(空白的后者预填充的表单)

    • POST非法数据(通常重新显示带有错误信息的表单)

    • POST合法数据(提交数据并重定向)

     

    为了将你从这些烦人的重复步骤中解救出来,Django为表单提供了一类通用视图

     

    基础表单

    这是一个简单的联系表单:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 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来构造:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 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(ContactView, self).form_valid(form)

    注意:

    • FormView是从TemplateResponseMixin来的,所以可以使用template_name

    • 默认的form_valid()只是简单的重定向到success_url

     

    模型表单

    在处理模型的时候,通用视图才能大显身手。只要可以找到要处理的模型类,这些通用视图会自动创建ModelForm:

    • 如果指明了model属性,那个模型类将被选择

    • 如果get_object()返回了一个对象,那个对象的类将会被选择

    • 如果指明了queryset,相关的模型将会被选择

     

    模型表单视图提供form_valid()方法来自动保存模型。如果有特殊需要,你可以重写它,看下面的例子

    你甚至不必为CreateView和UpdateView指明success_url,他们会自动选择模型对象中的get_absolute_url()(如果存在的话)你也可以简单地设置form_class来定制一个ModelForm(为模型添加额外的验证)

     

    注意当指定一个定制的表单类时,你也必须指定模型,尽管form_class可能就是一个ModelForm

     

    首先我们需要添加为Author类添加get_absolute_url()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 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})

    然后我们使用CreateView和它的朋友们来做实际的工作。注意我们在这里如何匹配基于类的通用视图,我们不必写任何的逻辑代码:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 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
     
    class AuthorUpdate(UpdateView):
        model = Author
     
    class AuthorDelete(DeleteView):
        model = Author
        success_url = reverse_lazy('author-list')

    注意:这里必须要用reverse_lazy(),而不仅仅是reverse,因为当文件被导入时urls没有被加载

    最后,我们在URLconf中加上这些新的视图:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # urls.py
    from django.conf.urls import patterns, url
    from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete
     
    urlpatterns = patterns('',
        # ...
        url(r'author/add/$', AuthorCreate.as_view(), name='author_add'),
        url(r'author/(?P<pk>d+)/$', AuthorUpdate.as_view(), name='author_update'),
        url(r'author/(?P<pk>d+)/delete/$', AuthorDelete.as_view(), name='author_delete'),
    )

    注意:这些视图都继承于SingleObjectTemplateMinxin,这个类使用template_name_suffix来构造基于模型的template_name

    在这个例子中:

    • CreateView和UpdateView使用myapp/author_form.html

    • DeleteView使用myapp/author_confirm_date.html

    如果你想要为CreateView和UpdateView使用不同的模板,你可以在你的视图类里设置template_name或者template_name_suffix

     

    模型和request.user

    为了跟踪用户使用CreateView创建对象,你可以使用定制的ModelForm来实现它。

    首先,为模型增加外键:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # models.py
    from django.contrib.auth import User
    from django.db import models
     
    class Author(models.Model):
        name = models.CharField(max_length=200)
        created_by = models.ForeignKey(User)
     
        # ...

    创建一个定制的ModelForm来隔离created_by,以免用户去编辑它:

    1
    2
    3
    4
    5
    6
    7
    8
    # forms.py
    from django import forms
    from myapp.models import Author
     
    class AuthorForm(forms.ModelForm):
        class Meta:
            model = Author
            exclude = ('created_by',)

    在这个视图中,使用定制的form_class并重写form_valid()来增加user:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # views.py
    from django.views.generic.edit import CreateView
    from myapp.models import Author
    from myapp.forms import AuthorForm
     
    class AuthorCreate(CreateView):
        form_class = AuthorForm
        model = Author
     
        def form_valid(self, form):
            form.instance.created_by = self.request.user
            return super(AuthorCreate, self).form_valid(form)

    注意你需要使用login_required()来装饰这个视图,或者在form_valid()里处理未登录的用户

     

    AJAX例子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import json
     
    from django.http import HttpResponse
    from django.views.generic.edit import CreateView
     
    class AjaxableResponseMixin(object):
        """
        Mixin to add AJAX support to a form.
        Must be used with an object-based FormView (e.g. CreateView)
        """
        def render_to_json_response(self, context, **response_kwargs):
            data = json.dumps(context)
            response_kwargs['content_type'] = 'application/json'
            return HttpResponse(data, **response_kwargs)
     
        def form_invalid(self, form):
            response = super(AjaxableResponseMixin, self).form_invalid(form)
            if self.request.is_ajax():
                return self.render_to_json_response(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 self.render_to_json_response(data)
            else:
                return response
     
    class AuthorCreate(AjaxableResponseMixin, CreateView):
        model = Author

    转载请注明出处

  • 相关阅读:
    20189221 2018-2019-2 《密码与安全新技术专题》第五周作业
    2018-2019-2 20189221 《网络攻防技术》第九周作业
    2018-2019-2 20189221 《网络攻防技术》第八周作业
    20189221 2018-2019-2 《密码与安全新技术专题》第四周作业
    2018-2019-2 20189221 《网络攻防技术》第七周作业
    2018-2019-2 20189221 《网络攻防技术》第六周作业
    20189221 2018-2019-2 《密码与安全新技术专题》第三周作业
    2018-2019-1 20189203《Linux内核原理与分析》第五周作业
    2018-2019-1 20189203《Linux内核原理与分析》第四周作业
    2018-2019-1 20189203《Linux内核原理与分析》第三周作业
  • 原文地址:https://www.cnblogs.com/huafeng/p/3273421.html
Copyright © 2020-2023  润新知