前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django内置的通用类视图CBV及示例

Django内置的通用类视图CBV及示例

作者头像
菲宇
发布2019-10-22 14:45:48
3.2K0
发布2019-10-22 14:45:48
举报
文章被收录于专栏:菲宇菲宇

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/bbwangj/article/details/98720627

Class-based views是Django为解决建站过程中的常见的呈现模式而建立的。具有如下几个原则:

  • 代码越少越好
  • 永远不要重复代码
  • View应当只包含呈现逻辑, 不应包括业务逻辑
  • 保持view逻辑清晰简单
  • 不要将CBVs用作403, 404, 500的错误处理程序
  • 保持mixin简单明了

django自带的view如下表所示:

类名

功能

例子

View

基本View, 可以在任何时候使用

见后面详细介绍

RedirectView

重新定向到其他URL

将访问"/log-in/"的用户重新定向到"/login/"

TemplateView

显示Django HTML template

一般网站中使用模板显示的页

ListView

显示对象列表

文章列表页

DetailView

显示对象详情

文章详细页

FormView

提交From

网站联系我们或emai订阅form

CreateView

创建对象

创建新文章页

UpdateView

更新对象

修改文章页

DeleteView

删除对象

删除文章页

Generic date views

显示一段时间内的对象

按时间归类的博客

1.ListView

表示对象列表的一个页面. 执行这个视图的时候,self.object_list将包含视图正在操作的对象列表(通常是一个查询集,但不是必须). 属性:

  • model: 指定模型
  • tempalta_name:模板文件
  • queryset:指定一个经过过滤的对象列表,将取代model提供的值
  • context_object_name: 指定要在上下文中使用的变量的名称

方法:

  • get_queryset():获取此视图的对象列表.必须是可迭代或者可以使查询集.默认返回queryset属性.可以通过重写该方法实现动态过滤.让这种方式能够工作的关键点,在于当类视图被调用时,各种有用的对象被存储在self上,同request(self.request)一样,其中包含了从URLconf中获取到的位置参数(self.args)和关键字参数(self.kwargs).
  • get_context_data(**kwargs): 返回显示对象的上下文数据,通过覆盖该方法返回额外的上下文 2.DetailView

执行这个视图的时候,self.object将包含视图正在操作的对象. 属性:

  • model: 视图要显示的模型
  • queryset: 表示对象的一个查询集.queryset的值优先于model的值.
  • template_name: 字符串表示的模板名称.
  • context_object_name: 指定在上下文中使用的变量的名称.
  • pk_url_kwarg: URLconf中,包含逐渐的关键字参数的名称.默认为'pk'.
  • get_context_data:返回显示对象的上下文数据.

方法:

  • get_queryset():返回用来获取本视图显示对象的queryset.如果设置了queryset属性,get_queryset()默认返回它的值.
  • get_object(queryset=None):返回该视图要显示的单个对象.如果提供了queryset,该queryset将作为对象的查询源,否则,将使用get_queryset().get_object()从视图的所有参数中查找pk_url_kwarg参数,如果找到了这个参数,该方法使用这个参数的值执行一个基于逐渐的查询.如果这个参数没有找到,该方法查找slug_url_kwarg参数,使用slug_field字段执行针对slug的查询.当query_pk_and_slugTrue时,get_object()将使用主键和slug执行查询.
  • get_context_data(**kwargs):返回显示对象的上下文数据.这个方法的基本实现需要object属性被视图赋值(即使是None).它返回一个包含这些内容的字典: object:这个视图显示的对象(self.object) context_object_name:self.object也将存储在get_context_object_name()返回的名称中,该名称默认为模型的小写名称. 3.FormView

显示表单的视图,验证错误时,重新显示表单并显示错误信息;成功时,重定向到一个新的URL. 属性:

  • form_class:要实例化的Form类.
  • success_url:表单成功处理后重定向到的URL.
  • tamplate_name:字符串表示的模板名称. 方法:
  • get_success_url():决定在表单成功验证后重定向到的URL,默认返回success_url.
  • form_valid(form):在表单验证成功后调用该方法(注意并没有对数据进行操作,例如保存!),并重定向到get_success_url(),可以覆盖该方法在以上行为之间添加额外的动作.该方法必须返回一个HttpResponse.
  • form_invalid(form):如果表单验证失败,则使用已填充的表单数据和错误信息重新渲染上下文.
  • get_context_data(**kwargs):返回显示对象的上下文数据. 4.CreateView

显示用于创建对象的表单的视图,通过验证错误信息重新显示视图,并且保存对象. 属性:

  • tamplate_name:
  • form_class:
  • fields:字段名称列表,其解释方式与ModelFormMeta.fields相同.如果你是自动生成表单类,那么该属性不能省略.
  • success_url:
  • model:
  • queryset:
  • context_object_name:
  • pk_url_kwarg: 方法:
  • get_queryset():
  • get_object():
  • form_valid():
  • get_context_data(**kwargs): (未填写属性和方法的使用同上) 5.UpdateView

显示用于编辑现有对象的表单的视图,重新显示具有验证错误信息的视图,并且保存对象.这里使用从对象模型自动生成的表单(除非手动制定表单类). 该视图用法与CreateView基本相同,仅在BaseUpdateView中对get()post()的内部实现有区别.

6.DeleteView

显示确认页面并删除现有对象的视图.仅当请求方法为POST时,才会删除给定的内容.如果此视图是通过GET提取的,它将显示一个确认页面,其中包含POST到同一网址的表单. 属性:

  • tamplate_name:
  • success_url:
  • model:
  • queryset:
  • context_object_name:
  • pk_url_kwarg: **方法:*
  • get_object():
  • get_queryset():
  • *get_context_data(**kwargs):*
  • delete(request, args, **kwargs):*在获取到的对象上调用delete()方法,然后重定向到success_url.

实例

1、创建django工程,创建名为crud的app,此处略过

2、 修改models.py

代码语言:javascript
复制
class employee(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=60)
    city = models.CharField(max_length=60)
    email = models.EmailField(max_length=30)
    phone = models.CharField()
    wechat = models.CharField(max_length=30)
    QQ = models.CharField()
    def __unicode__(self):
        return self.name
    class Meta:
        ordering = ["-id"]

3、配置

代码语言:javascript
复制
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'crud',
]

4、数据迁移

代码语言:javascript
复制
python manage.py makemigrations crud
python manage.py migrate crud

5、修改urls,views

crud中的urls

代码语言:javascript
复制
from django.conf.urls import url
from crud import views

urlpatterns = [
    url(r'^$', views.EmployeeList.as_view(), name='employee_list'),
    url(r'^add', views.EmployeeCreate.as_view(), name='employee_add'),
    url(r'^update/(?P<pk>\d+)$', views.EmployeeUpdate.as_view(), name='employee_update'),
    url(r'^delete/(?P<pk>\d+)$', views.EmployeeDelete.as_view(), name='employee_delete'),
    url(r'employee_detail/(?P<pk>\d+)/$', views.EmployeeDetail.as_view(), name='employee_detail'),
]

工程中urls

代码语言:javascript
复制
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^crud/', include('crud.urls')),
]
代码语言:javascript
复制
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render, redirect
# Create your views here.
from django.http import HttpResponse, HttpResponseRedirect
from django.views.generic import TemplateView,ListView
from django.utils import timezone
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from crud.models import employee

class EmployeeList(ListView):
    model = employee

class EmployeeCreate(CreateView):
    model = employee
    success_url = reverse_lazy('employee_list')
    fields = ['id', 'name', 'address', 'city', 'email', 'phone', 'wechat', 'QQ']
    def add(request):
        form = employee(request.POST or None)
        if form.is_valid():
            instance.save()
        context = {
            'form': form,
        }
        #如果没有有效提交,则仍留在原来页面
        return render(request, 'employee_list.html',  context)

class EmployeeUpdate(UpdateView):
    model = employee
    success_url = reverse_lazy('employee_list')
    fields = ['id', 'name', 'address','city', 'email', 'phone','wechat','QQ']

class EmployeeDelete(DeleteView):
    model = employee
    success_url = reverse_lazy('employee_list')

class EmployeeDetail(DetailView):
    model = employee   #将 model 指定为Publisher,告诉 Django 我要获取的模型是 Publisher。
    context_object_name = 'employee_detail'   #指定获取的模型列表数据保存的变量名。这个变量会被传递给模板。
    def get_context_data(self, **kwargs):
        context = super(EmployeeDetail, self).get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context

6、新建模板 employee_list.html

代码语言:javascript
复制
<ul>
    {% for emp in object_list %}
    <li>{{ emp.id }} &nbsp &nbsp {{ emp.name }} &nbsp &nbsp{{ emp.address }}&nbsp &nbsp{{ emp.city }} &nbsp &nbsp
        {{ emp.email }} &nbsp &nbsp{{ emp.phone }}&nbsp &nbsp{{ emp.wechat }} &nbsp &nbsp{{ emp.QQ }}:
    <a href="{% url "employee_update" emp.id %}">修改</a>
    <a href="{% url "employee_delete" emp.id %}">删除</a>
    </li>&nbsp
    {% endfor %}
</ul>

<a href="{% url "employee_add" %}">新增</a>

employee_form.html

代码语言:javascript
复制
    <title>Title</title>
    <form method="post">
        <table>
            {% csrf_token %}
            {{ form }}
        </table>
    <input type="submit" value="Submit" />
</form>

employee_confirm_delete.html

代码语言:javascript
复制
<form method="post">{% csrf_token %}
确实要删除 "{{ object }}" ?
<input type="submit" value="Submit" />
</form>

employee_detail.html

代码语言:javascript
复制
<h1>你好,{{ object.name }}</h1>
<h2>工号:{{ object.id }}</h2>
<p>姓名:{{ object.name }}</p>
<p>邮箱地址:{{ object.email }}</p>
<p>所在城市: {{ object.city }}</p>
<p>电话号码: {{ object.phone }}</p>
<p>详细地址: {{ object.address }}</p>
<p>微信: {{ object.wechat }}</p>
<p>QQ: {{ object.QQ }}</p>

7、启动服务python manage.py runserver

浏览器中输入 http://127.0.0.1:8000/crud/ 即可对员工进行增加、删除、修改

-----UpdateView和CreateView-----

我们有了Project和Schedule列表显示后,现在需要添加新增和修改的操作。可以直接用Django通用视图里的UpdateView和CreateView。根据官网文档的例子,我们先在projtrack/views.py中添加项目新增和修改视图的代码:

代码语言:javascript
复制
    # projtrack/views.py
    ...
    # 修改项目视图
    class ProjUpdView(generic.UpdateView):
        model = Project
        fields = ['project_name', 'description', 'project_status']
        template_name = 'projtrack/update_form.html'
     
    # 新增项目视图
    class ProjNewView(generic.CreateView):
        model = Project
        fields = ['project_name', 'description', 'project_type', 'project_status']
        template_name = 'projtrack/update_form.html'
    ...

因为编辑和新增页面的前端代码基本一样,我们在这里都指定了template为update_form。也可指定不同的模板。另外也可用template_name_suffix参数去指定模板。比如,如果设定template_name_suffix = '_create_form', 则用到的模板将会是projtrack/project_create_form.html。

这里projtrack/update_form.html代码如下:

代码语言:javascript
复制
    {% extends "projtrack/index.html" %}
    {% block body %}
    {% if user.is_authenticated %}
    <form method="post">{% csrf_token %}
        {{ form.as_p }}
        <input class="btn btn-default" type="submit" value="Update" />
    </form>
    {% endif %}
    {% endblock %}

注意:

在所有的 POST 表单元素时,需要加上一个 {% csrf_token %} tag。这是Django提供的CSRF防护机制。 {{ form.as_p }} 表示渲染表单为一系列的p标签,每个p标签包含一个字段:

代码语言:javascript
复制
<p>
    <label for="id_subject">Subject:</label>
    <input id="id_subject" type="text" name="subject" maxlength="100" />
</p>

其它form在模版中的渲染方式还包括:

form.as_ul:渲染表单为一系列的li标签,每个li 标签包含一个字段 form.as_table:输出表单为一个HTML的table。 for field in form:通过迭代form,获取其中的所有field。field可引用的包括:{{ field.label_tag }} , {{ field }} , {{ field.errors }} 。{{ field.label_tag }}输出为field的label元素,{{ field }}输出为field的input,{{ field.errors }}为field的errors元素(errors一般在form验证出错的时候显示)。 form.fieldname:直接将form作为一个dict,引用其每一个field,比如{{ form.title }} 引用form中的title这个field。这种方式一般用于form需要更加精准的样式的时候,逐个元素逐个元素的编排到html中。

完成后可在页面上新增或修改项目信息。不过点击Update后会有一个报错:191989-055d8b7a362f2603.png

意思是新增后修改完成后我们没有定义一个redirect的url去跳转。根据报错的提示,我们可以直接在视图下给success_url参数赋值,或在模型中去定义get_absolute_url()方法,去设置成功后跳转的url。这里我们在模型中添加:

代码语言:javascript
复制
# projtrack/model.py    
class Project(models.Model):
    ...
    def get_absolute_url(self):
        return reverse('projtrack:project')

这样,在新增或修改项目成功就就跳转到项目列表页面

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.ListView
  • 6.DeleteView
  • 实例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档