类视图
- 类视图基础
- 类视图引入
- 视图函数(以函数的方式定义的视图),一个视图对应的路径,提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,引入类视图
- 类视图(使用类来定义一个视图),类视图可以将视图对应的不同请求方式以类中的不同方法来区别定义
- 类视图的使用
- 定义类视图需要继承自Django提供的父类View
- 配置路由时,使用类视图的as_view()方法来添加
urlpatterns = [
# 视图函数:注册
# url(r'^register/$', views.register, name='register'),
# 类视图:注册
url(r'^register/$', views.RegisterView.as_view(), name='register'),
]
调用流程 as_view-->view-->dispatch
# 调用流程as_view-->view-->dispatch
# as_view是View类的一个类方法,返回真正的视图函数view
# 类方法as_view中有一个view(request, *args, **kwargs)方法,返回分发函数dispatch(request, *args, **kwargs)
# dispatch是View类的方法,按照不同的请求方式调用不同请求方法,判断请求方式是否在列表http_method_names中
获取属性getattr('对象','字符串')
- 类视图添加装饰器
先定义一个为函数视图准备的装饰器(在设计装饰器时基本都以函数视图作为考虑的被装饰对象),及一个要被装饰的类视图
方式一:在URL配置中装饰,为类视图中的所有请求方法都加上装饰器行为(因为是在视图入口处,分发请求方式前)
urlpatterns = [
url(r'^demo/$', my_decorate(DemoView.as_view()))
]
方式二:在类视图中装饰, 在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器,需要使用method_decorator将其转换为适用于类视图方法的装饰器
@method_decorator(decorator,name)
method_decorator装饰器使用name参数指明被装饰的方法
name='dispatch', 为全部请求方法添加装饰器
name='get', 为特定请求方法添加装饰器
为类视图的多个方法添加装饰器,但不是所有的方法,直接在需要添加装饰器的方法上使用method_decorator
@method_decorator(decorator)
- 类视图Mixin扩展
面向对象多继承的特性,通过定义父类(作为扩展类),在父类中定义想要向类视图补充的方法,类视图继承这些扩展父类,便可实现代码复用。
定义的扩展父类名称通常以Mixin结尾
class BooksView(CreateModelMixin, ListModelMixin, View):
#同时继承两个扩展类,复用CreateModelMixin和ListModelMixin中的方法,如果该方法不存在,再在View类中查找该方法
中间件
- 中间件定义
中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,在Django处理视图的不同阶段对输入或输出进行干预
定义一个中间件工厂函数,返回一个可以被调用的中间件(可以被调用的对象,像视图一样接收request对象参数,返回response对象),接收一个可以调用的get_response对象。
定义好中间件后,需要在settings.py 文件中添加注册中间件
注意:Django运行在调试模式下,中间件init部分有可能被调用两次
def simple_middleware(get_response):
# 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。
def middleware(request):
# 此处编写的代码会在每个请求处理视图前被调用。
response = get_response(request)
# 此处编写的代码会在每个请求处理视图之后被调用。
return response
return middleware
-
多个中间件的执行顺序
在请求视图被处理前,中间件由上至下依次执行
在请求视图被处理后,中间件由下至上依次执行
模板
Django自带模板
- 模板基本概念
1.模板配置
在工程中创建模板目录templates--->settings.py配置文件中修改TEMPLATES配置项的DIRS值--->在templates目录中新建一个模板文件,如index.html--->Django提供了一个函数render实现模板渲染
render(request对象, 模板文件路径, 模板数据字典)
- 模板变量(可以是python的内建类型,也可以是对象)(变量名必须由字母、数字、下划线(不能以下划线开头)和点组成)
{{变量}}
3.模板语法
- 模板变量(可以是python的内建类型,也可以是对象)(变量名必须由字母、数字、下划线(不能以下划线开头)和点组成)
for循环
{% for item in 列表 %}
{% 循环语句 %}
{% endfor %}
if条件
{% if ... %}
逻辑1
{% elif ... %}
逻辑2
{% else %}
逻辑3
{% endif %}
注意:运算符左右两侧不能紧挨变量或常量,必须有空格。
- 模板使用和继承
- 过滤器
使用管道符号|来应用过滤器,用于进行计算、转换操作,可以使用在变量、标签中。
如果过滤器需要参数,则使用冒号:传递参数。变量|过滤器:参数
date,日期,对日期类型的值进行字符串格式化value|date:"Y年m月j日 H时i分s秒"
2.自定义过滤器
在各自app里建一个templatetags包--->在包里创建一个要在HTML文件引用的py文件--->在py文件中,先导入from django import template--->实例化对象register = template.Library()--->创建一个template能认识的函数--->对创建的每一个过滤器,都要用加上装饰器--->在HTML文件中引用{% load py文件 %}---> 使用过滤器{{ 参数 | 过滤器 }} - 模板继承
父模板
多个模板中某些内容相同,将这段内容定义到父模板中,
标签block:在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。 建议给endblock标签写上名字,同对应的block名字。
{% block 名称 %}
预留区域,可以编写默认内容,也可以没有默认内容
{% endblock 名称 %}
子模板
标签extends:继承,写在子模板文件的第一行{% extends "父模板路径"%}
子模版不用填充父模版中的所有预留区域,如果子模版没有填充,则使用父模版定义的默认值。
填充父模板中指定名称的预留区域
{% block 名称 %}
实际填充内容
{{ block.super }}用于获取父模板中block的内容
{% endblock 名称 %}
- 模板注释
{#...#} #单行注释
{% comment %} #多行注释
...
{% endcomment %}
Jinja2模板
配置
项目文件中创建 jinja2_env.py 文件--->在settings.py文件,修改TEMPLATES 中的 'BACKEND'(jinja2.Jinja2)和'environment'('jinja2_env.environment')
在jinja2_env.py文件中自定义过滤器
from jinja2 import Environment
from datetime import datetime
def environment(**options):
env = Environment(**options)
# 2.将自定义的过滤器添加到环境中
env.filters['do_listreverse'] = do_listreverse
env.filters['adate'] = adate
return env
# 1.自定义过滤器
def do_listreverse(li):
if li == 'B':
return 'haha'
def adate(timestr):
#{{变量 | 过滤器(“param1”,“param2”)}}本身的变量不需要传入,param1是自动传入的,第一个param1是format
# strftime()函数是用来格式化一个日期,日期时间和时间的函数
# strptime()函数就是从字符串表示的日期时间按格式化字符串要求转换为相应的日期时间
# return datetime.strftime(timestr,format("%Y-%m-%d"))
return datetime.strftime(timestr,format("%Y年%m月星期%w-%d日"))
在模板文件中引用<h2>{{ years | adate }}</h2>
数据库
- ORM框架
- Object:对象-类
Relations:关系,关系数据库中的表
Mapping:映射,建立O和R之间的对应关系 - ORM框架将类和数据表进行对应,通过类和对象即可操作数据表,不用写SQL语句
- ORM根据设计的类自动生成数据库中的表
在应用的models.py文件中设计和表对应的类(模型类)
-
使用django进行数据库开发的步骤如下:
配置数据库连接信息--->在models.py中定义模型类--->迁移--->通过类和对象完成数据增删改查操作
3.配置
- 使用MySQL数据库首先需要安装驱动程序pip install PyMySQL
- 在工程同名子目录的init.py文件中添加以下代码,让Django的ORM能以mysqldb的方式来调用PyMySQL
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
-修改DATABASES配置信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'mysql', # 数据库用户密码
'NAME': 'django_demo' # 数据库名字
}
}
-在MySQL中创建数据库create database django_demo default charset=utf8;
- 定义模型类
- 模型类被定义在"应用/models.py"文件中。
- models.py中设计的模型类必须继承于models.Model类
- 模型类的类属性对数据表中的字段
数据库表名(模型类未指明表名,默认为小写app应用名_小写模型类名)
主键(django为表创建自动增长的主键列,每个模型只能有一个主键列),不在模型类中声明,默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key
属性命名限制(不能是关键字,不允许使用连续的下划线,与查询方式冲突)
定义属性时需要指定字段类型,通过字段类型的参数指定选项
属性=models.字段类型(选项)
字段类型:CharField,字符串,参数max_length表示最大字符个数,DateField 日期类型 ...
选项:unique,null是数据库验证,blank是表单验证
迁移(将模型类同步到数据库中)
python manage.py makemigrations #生成迁移文件(根据模型类生成的)
python manage.py migrate #同步到数据库中
- 数据库的增删改查
- 增
法一:创建模型类对象,执行对象的save()方法,先创建再保存
法二:模型类.objects.create()保存,创建和保存同时进行 - 删
法一:模型类对象.delete()hero = HeroInfo.objects.get(id=13)
先过滤再删除
法二:模型类.objects.filter().delete()HeroInfo.objects.filter(id=14).delete()
过滤删除同时进行 - 改
法一:修改模型类对象的属性,然后执行save()方法, 先修改再保存
法二:使用模型类.objects.filter().update(),修改和保存同时进行 - 查
基本查询:
get 查询单一结果,不存在会抛异常BookInfo.objects.get(id=3)
all 查询多个结果 BookInfo.objects.all()
count 查询结果数量 BookInfo.objects.count()
过滤查询:
filter 过滤出多个结果 BookInfo.objects.filter(id__exact=1)
exclude排除掉符合条件剩下的结果 BookInfo.objects.exclude(id=3)
get 过滤单一结果BookInfo.objects.get(id=3)
属性名称__比较运算符=值, 中间是两个下划线,
exact:表示判等
contains:是否包含(模糊查询)
startswith、endswith:以指定值开头或结尾
以上运算符, 在运算符前加上i表示不区分大小写
isnull:是否为null
in:是否包含在范围内。
gt 大于---gte 大于等于---lt 小于---lte 小于等于
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算
以上都是比较运算符
F查询:要导入F对象,F(属性名):属性与属性进行比较,在F对象上可以使用算数运算
BookInfo.objects.filter(bread__gte=F('bcomment'))
BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
Q对象:导入Q对象,多个过滤器逐个调用表示逻辑与关系,实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象前使用~操作符,表示非not
BookInfo.objects.filter(bread__gt=20,id下划线下划线lt=3)
BookInfo.objects.filter(Q(bread__gt=20) \| Q(pk下划线下划线lt=3))
BookInfo.objects.filter(~Q(pk=3))
聚合查询:
aggregate()过滤器调用聚合函数(聚合函数包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 求和)
BookInfo.objects.aggregate(Sum('bread'))
使用count时一般不使用aggregate()过滤器,count函数的返回值是一个数字
排序:
orderby
BookInfo.objects.all().order_by('bread') # 升序
BookInfo.objects.all().order_by('-bread') # 降序
关联查询:
由一到多的访问语法:一对应的模型类对象.多对应的模型类名小写_set
由多到一的访问语法:多对应的模型类对象.多对应的模型类中的关系类属性名
访问一对应的模型类关联对象的id语法:多对应的模型类对象.关联类属性_id
关联过滤查询:
由多模型类条件查询一模型类数据:
关联模型类名小写__属性名__条件运算符=值
,如果没有"运算符"部分,表示等于
由一模型类条件查询多模型类数据:
一模型类关联属性名__一模型类属性名__条件运算符=值
,如果没有"运算符"部分,表示等于
- 通过模型类操作数据表
1.workon 虚拟环境 ,进入虚拟环境
2.python manage.py shell ,进入项目终端
3.导入生成的表
4.创建类的实例对象
5.给实例对象添加实例属性(同类中创建的类属性)
6.调用继承自models.Model类的的save()方法,将添加的属性添加到数据表中
7.获取表中的数据:对象=类名.objects.get(条件),得到的值保存在对象中
8.通过7中的对象进行更新数据和删除
- 查询集QuerySet
从数据库中获取的对象集合。当调用如下过滤器方法时,Django会返回查询集,对查询集可以再次调用过滤器进行过滤(查询集可以含有零个、一个或多个过滤器)BookInfo.objects.filter(bread__gt=30).order_by('bpub_date')
:
all():返回所有数据。
filter():返回满足条件的数据。
exclude():返回满足条件之外的数据。
order_by():对结果进行排序。
判断某一个查询集中是否有数据:
exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。
- 两大特性:
惰性执行(创建查询集不会访问数据库,调用数据才会访问数据库)
缓存,使用同一个查询集,第一次使用时会发生数据库的查询,缓存结果,再次使用查询集时会使用缓存的数据,减少了数据库的查询次数
限制查询集(对查询集进行取下标或切片操作qs = BookInfo.objects.all()[0:2]
)
对查询集进行切片后返回一个新的查询集,不会立即执行查询
获取一个对象,直接使用[0],等同于[0:1].get(),如果没有数据,[0]引发IndexError异常,
[0:1].get()如果没有数据引发DoesNotExist异常