DRF全局总结
基础部分
一、创建工程
1、创建虚拟环境
python -m venv 路径
2、安装Django
进入虚拟环境 pip install Django
3、创建项目
django-admin startproject 项目名.
注意:这里是已经创建的虚拟环境,再在下面创建项目,这时使用虚拟环境的名称后面加个’.'这样创建出来的项目不会出现多个层级
4、创建子应用
python manage.py startapp 子应用名 # python manage.py startapp projects
5、注册子应用
在setting - > INSTALLED_APPS中添加
6、设置路由
7、创建视图
二、接收数据处理
1、请求体数据
当在body中传送的json数据,是以byte传送的。(要写解码,在把文本转成字典)
2、pk接受
3、数据返回JsonResponse
三、ORM框架
1、关联数据库
a、创建数据库和用户
b、配置数据库
settings.py文件中配置对应的IP、用户名、密码、数据库
c、安装mysqlclient
d、安装 pymysql
项目__init__.py文件中加入下面内容
import pymysql
pymysql.install_as_MySQLdb()
e、安装 cryptography
2、数据库的增删改查
from django.db.models import Q from django.http import JsonResponse from django.shortcuts import render, HttpResponse from django.views import View from app01.models import Projects def projects(request): # 创建数据 # 方法一 # one_obj = Projects(name='小假123', leader='小块2', tester='小时2', # programer='大赛2', publish_app='时间控制器2', desc='这是一个时间的项目2') # print(one_obj) # one_obj.save() # 方法二 # Projects.objects.create(name='小假1234', leader='小块24', tester='小时24', # programer='大赛24', publish_app='时间控制器24', desc='这是一个时间的项目24') # 增加外键的值 外键=关联模型对象(一对象) # 外键_id = 关联的模型对象.id # 添加interface的interface_id(interface(多)project(一)) # interface = project # interface_id = project_id # 查 # 1、获取一个数据的所有记录 # QuerySet查询集, 就相当于一个列表(存放所有项目对象的列表) # queryset查询集,简单理解为被那条件筛选后满足条件的一个表,要想得到想要的结果,可以继续筛选 # qs = Projects.objects.all() # for i in qs: # print(f'{type(i)}') # print(i) # 2、获取摸一个指定的记录,get() # get方法只能返回一条记录 # 如果返回多条记录或查询记录不存在那么会抛出异常 # get方法的参数往往为主键或者唯一键 # data_project = Projects.objects.get(id=1) # data = data_project.leader # 3、获取某一些记录,filter()或者exlude() # 使用filter返回的是满足条件之后的queryset,exlude是不满足条件的queryset # data_project = Projects.objects.filter(leader__contains=2) # qs_project = Projects.objects.exclude(leader__icontains=2) # print(type(qs_project)) # data = qs_project.get(id=5) # 4、关联查询 # 外键字段__从表字段名__ # qs_project = Projects.objects.filter(interface__name='Login') # data = qs_project[0] # 5、比较查询 # __gt > # __gte >= # __lt < # __lte <= # qs_data = Projects.objects.filter(id__gt=5) # data = qs_data.get(id=9) # 6、逻辑关系,多个条件查询 # 如果给filter指定多个条件,那么条件之间与的关系 # qs_data = Projects.objects.filter(id__gt=5,leader__contains=2) # data = qs_data.get(id=7) # # Q或条件 F # qs_data = Projects.objects.filter(Q(id__gt=5) | Q(leader__contains=2)) # data = qs_data.get(id=7) # 7、查询集的操作 # 查询集相当于一个列表,支持列表中的的大多数操作 # 查询集是对数据库操作的一种优化 # 查询集会缓存结果 # 惰性查询 # 查询集,简单理解为被那条件筛选后满足条件的一个表,要想得到想要的结果,可以继续筛选 # 8、排序 # 默认为从小到大排序 # 在字段前面添加-号,代表从大到小排序 # qs_data = Projects.objects.filter(id__gt=5).order_by('-name') # data = qs_data.first() # return HttpResponse(data) # 更新操作 # 1、现获取到要修改的模型对象 # 2、修改 # 3、保存 # one_data = Projects.objects.get(id=9) # one_data.name = '这是一个更新操作' # one_data.save() # Projects.objects.get(id=9).update(name='更新操作') # 删除操作 # 1、先获取要删除的模型对象 # 2、删除 # one_data = Projects.objects.get(id=2) # one_data.delete() # Projects.objects.get(id__in=[2,7]).delete() # return HttpResponse("OK")
# 获取数据 # 方法一获取所有数据,返回一个QuerySet查询集 # h = Projects.objects.all() # print(h[:1]) # for i in h: # print(i.name) # 1获取特定某个指定的记录 ''' 1.get返回的是一个模型类对象 2.get只能查询一条数据,查询结果出现多条或者不存在就会报错 3,get主要用于主键和唯一值的查询 ''' # one_Projecr = Projects.objects.get(id=3) # 2读取部分数据 filter,exclude """ filter : 返回满足条件的查询集合 exclude : 返回不满足条件的查询集合 """ # #读取id为1的数据 # qs = Projects.objects.filter(id=1) # #读取ID不为1的数据 # qs1 = Projects.objects.exclude(id=1) # 3模糊查询 # mh = Projects.objects.filter(leader__contains='icon') #包含icon # mh1 = Projects.objects.filter(leader__icontains='con') #忽略查询结果的大小写icon # mh2 = Projects.objects.filter(leader__startswith='i') #以i开头的 # mh3 = Projects.objects.filter(leader__istartswith='') # 忽略大小 # mh4 = Projects.objects.filter(leader__endswith='n') #以n结尾的 # mh5 = Projects.objects.filter(leader__iendswith='n') # mh6 = Projects.objects.filter(leader__regex='') #正则匹配 # mh7= Projects.objects.filter(leader__iregex='') # mh8 = Projects.objects.filter(leader__exact='icon') #精确匹配 # mh9 = Projects.objects.filter(leader__iexact='icon') # mh10 = Projects.objects.filter(leader__in=['icon','宋茜'])#包含 # 4关联查询 ''' 格式 外键字段__从表字段名__ 如果是多个表 A表__C表__从表字段名_ ''' # qs = Projects.objects.filter(project2s__name__contains='创建项目') # 5比较查询 """ __gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于 返回查询集 """ # qs = Projects.objects.filter(id__gt=3) #6逻辑查询 ''' 可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象 允许组合正常的查询和取反(NOT) 查询 '~' ''' # qs1 =Projects.objects.filter(name='接口自动',leader='宋茜') #且的关系 # from django.db.models import Q # qs1 = Projects.objects.filter(Q(leader='icon')|Q(leader='宋茜')) #或的关系 # qs2 = Projects.objects.filter(Q(leader='icon')&~Q(tester='魏书')) #and的 #7.查询集的操作 """ 7.1 查询集相当与一个列表,支持列表的大多数就操作(数字索引,正向切片,for循环) 7.2 查询集是对数据库的一种操作 7.3 查询及会缓存结果 7.4 惰性查询 7.5 查询集支持链式操作 first() 第一个 """ #获取链式查询的第一个结果 qs = Projects.objects.filter(leader__contains='icon').filter(tester__contains='小明1').first() qs = Projects.objects.filter(leader__contains='icon').filter(tester__contains='小明1').last()
#F查询两个字段的值做比较 """ Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。 Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。 """ from django.db.models import F qs = Projects.objects.filter(leader=F('tester'))
#分组查询 # qs = Project2s.objects.all().annotate(h = Count('project_id')) qs = Project2s.objects.values('project_id').annotate(Count('project_id'))
#聚合查询 ''' aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符 ,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。 为聚合值指定一个名称 名称 = 集合值标识符() ''' # from django.db.models import Max,Avg,F,Q,Min,Sum # qs = Projects.objects.all().aggregate(idmax = Max('id'),idmin=Min('id'),idavg = Avg('id'), # idsum =Sum('id'))
小结:
增
方法一:Projects(字段=“值”…)
方法二:Projects.objects.create(字段=“值”…)
查
一、all
- QuerySet查询集, 就相当于一个列表(存放所有项目对象的列表)
- queryset查询集,简单理解为被那条件筛选后满足条件的一个表,要想得到想要的结果,可以继续筛选
二、get
- get方法只能返回一条记录
- 如果返回多条记录或查询记录不存在那么会抛出异常
- get方法的参数往往为主键或者唯一键
三、filter()或者exlude()
- 使用filter返回的是满足条件之后的queryset,exlude是不满足条件的queryset
四、关联外键查询
- 外键字段__从表字段名
# 多查一 (objects.filter(多模型名小写_多的模型属性=值)) BookInfo.objects.filter(heroinfo_hname='大侠') # 一查多 (多.objects.filter(外键__一的属性=值)) HeroInfo.objects.filter(bookinfo__id__gt=1) # 多查一(先把多查出来,然后再利用多里面的外键 查到一) hero = HeroInfo.objects.get(hname='大侠') book = hero.hbook # 如果有外键直接当前模型对象.外键 代表获取外键模型对象 # 一查多(先把一查出来,然后用一.多的那个模型名小写_set 查到多) book = BookInfo.objects.get(id=1) book.heroinfo_set.all() # 如果当前没有外键的一方 应该是当前模型对象.多的一方模型小写_set
五、比较查询
- __gt >
- __gte >=
- __lt <
- __lte <=
六、逻辑关系,多个条件查询
- 如果给filter指定多个条件,那么条件之间与的关系
- Q或条件 F (Q(id__gt=5) | Q(leader__contains=2))
七、查询集的操作
- 查询集相当于一个列表,支持列表中的的大多数操作
- 查询集是对数据库操作的一种优化
- 查询集会缓存结果
- 惰性查询
- 查询集,简单理解为被那条件筛选后满足条件的一个表,要想得到想要的结果,可以继续筛选
八、排序 order_by(’-name’)
- 默认为从小到大排序
- 在字段前面添加-号,代表从大到小排序
九、聚合查询(aggregate)(点击看详情)
使用aggregate,聚合对应的字段
res=models.Book.objects.aggregate(c=Count("id"),max=Max("price"),min=Min("price")) print(res,type(res)
十、分组查询(annotate)(点击看详情)
annotate是先分组,后续使用values控制展示的字段
统计每一本以"菜"开头的书籍的作者个数: res = models.Book.objects.filter(title__startswith="菜").annotate(c = Count("authors__name")).values("title","c") print(res)
更新
- 现获取到要修改的模型对象
- 修改
- 保存
one_data = Projects.objects.get(id=9) one_data.name = '这是一个更新操作' one_data.save()
删除
- 先获取要删除的模型对象
- 删除
one_data = Projects.objects.get(id=2) one_data.delete()
序列化和反序列化
序列化:将模型对象转换为字典或者json的过程,叫做序列化的过程。 反序列化:将客户端传递的数据保存转化到模型对象的过程,叫做反序列化的过程。 核心: 1. 将数据库数据序列化为前端所需要的格式,并返回; 2. 将前端发送的数据反序列化为模型类对象,并保存到数据库中。
一、Django RestFrame Work 简介/安装
安装
安装: pip install djangorestframework
在settings.py的INSTALLED_APPS中添加’rest_framework’
INSTALLED_APPS = [ ... 'rest_framework', # 添加 ]
二、序列化器Serializer
Serializer序列化类定义
1、在子app下新建Serializers.py
2、定义序列化器
# 定义模型类
class 模型类(modles.Model):
模型字段 = models.字段类型(选项参数)
# 定义序列化器类
from rest_framework import serializers
class 序列化器类(serializers.Serializer):
序列化器字段= serializers.字段类型(选项参数
序列化器类(instance=None,data={},**kwargs) 1.进行序列化操作,将对象传递给instance 2.进行反序列化操作,将数据传递给data
模型类常用字段类型
AutoField: 自增长字段,通常不用,如果未在Model中显示指定主键,django会默认建立一个整型的自增长主键字段 BooleanField: 布尔型,值为True或False,在管理工具表现为checkbox CharField: 单行字符串字段,CharField有一个必填参数: CharField.max_length:字符的最大长度,django会根据这个参数在数据库层和校验层限制该字段所允许的最大字符数。 TextField: textarea字段,即多行文本字段 DateField: 日期字段 auto_now:当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 “last-modiied” 时间戳; auto_now_add:当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间。 IntegerField: 整型字段
Field的可选项: choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。 如SEX_CHOICES= ((‘F’,'Female’),(‘M’,'Male’),) default: 设定缺省值 primary_key: 设置主键,如果没有设置django创建表时会自动加上: unique: 数据唯一 unique_for_date: 日期唯一
verbose_name: 字段描述
help_text: 字段描述
null: 字段是否可以为空
外键 ForeignKey
# Student表和Teacher表一对多关系 # 在Students表新建下面外键 teacher=models.ForeignKey(Teacher,on_delete=models.CASCADE,related_name='student_teacher',default='')
# 第一个参数为关联的模型路径(应用名.模型类)或者模型类
# 第二个参数设置得是,当父表删除后,该字段的处理方式
# CASCADE 子表也会删除,
# SET_NULL 当前外键值会被设置为None
# PROJECT 会报错
# SET_DEFAULT 设置默认值,同时需要指定默认值,null=True
on_delete=models.CASCADE # 作用主表删除后字表也对应删除信息 related_name='student_teacher' # 使用teacher查询数据时,使用的关联关系 # 一查询多方式一 teacher = teacher.object.get(id=1) teacher.student_set.all() # 一查询多方式二 teacher = teacher.object.get(id=1) teacher.student_teacher.all()
序列化器字段类型
在定义序列化器类的字段时,write_only和read_only默认值为False,说明这个字段既在序列化时使用,也在反序列化时使用。
通用选项参数:
write_only: 设置为True,该字段只在序列化时使用,反序列化操作时不使用
read_only: 设置为True,该字段只在序列化时使用,反序列化时不使用
default: 设置序列化和反序列化时所使用的默认值
requird: 默认值是True,指明在进行反序化时此字段是否必须传入
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息
字段校验方式
# 单字段校验器 # 自定义校验器顺序 # 字段定义时的限制,包含了validators列表条目从左到右进行校验 -》但字段校验validate_字段名 # 单字段校验validate_字段名 # 校验之后一定要返回对应的值 def validate_name(self, value): if not value.endswith('项目'): raise serializers.ValidationError('项目名以"项目"结尾') # 校验之后一定要返回对应的值 return value # 多字段联合校验 def validate(self, attrs): if '小明' not in attrs['leader'] and '小明' not in attrs['tester']: raise serializers.ValidationError('"小明"必须是leader或者tester') return attrs
案例:
# 项目project表为父表("一"),接口表("多")为子表 class Interface(models.Model): name = models.CharField(verbose_name='接口名', max_length=200, unique=True, help_text='接口名') desc = models.TextField(verbose_name='简要描述', help_text='简要描述', blank=True, default='') # 第一个参数为关联的模型路径(应用名.模型类)或者模型类 # 第二个参数设置得是,当父表删除后,该字段的处理方式 # CASCADE 子表也会删除, # SET_NULL 当前外键值会被设置为None # PROJECT 会报错 # SET_DEFAULT 设置默认值,同时需要指定默认值,null=True project = models.ForeignKey('app01.Projects', on_delete=models.CASCADE, verbose_name='所属项目') class Meta: db_table = 'tb_interface' # 会在admin站点,显示更人性化的表名 verbose_name = '接口' verbose_name_plural = '接口' # 在admin中显示名字 def __str__(self): return self.name
数据库迁移命令
python manage.py makemigrations
python manage.py migrate
serializer.py
class HeroInfoSerializer(serializers.Serializer): name = serializers.CharField(label="英雄的名字") sex = serializers.CharField(label="性别", validators=[asster_django]) dsc = serializers.CharField(label="描述") # hbook = serializers.PrimaryKeyRelatedField(label="书籍", read_only=True) # 只能获取 # PrimaryKeyRelatedField获取外键的ID # hbook = serializers.PrimaryKeyRelatedField(label="书籍", queryset=Book.objects.all()) # 只能指定是Book中的书籍 # StringRelatedField获取外键的名字 # hbook = serializers.StringRelatedField(label="书籍") # hbook = BookInfoSerializer() def validate_name(self, value): if 'django' not in value.lower(): raise serializers.ValidationError('英雄名字中不包含django') return value def validate(self, attrs): if 'django' not in attrs['dsc'].lower(): raise serializers.ValidationError('dsc中不包含django') attrs['hello'] = '校验中新增' return attrs
ModelSerializer序列化类定义
class ProjectsModelSerializer(serializers.ModelSerializer): class Meta: # 指定参考哪一个模型类创建 model = Projects # 指定为模型类的哪些字段,来生产序列化器 fields = ‘__all__’
字段的约束条件设置
1、指定字段
fields = ('id', 'name', 'leader', 'tester', 'programer', 'publish_app')
2、不包含哪些字段
exclude = ('publish_app', 'desc')
3、指定哪些为只读字段
read_only_fields = ('publish_app', 'desc')
4、重写字段规则,具体规则和序列化一样
5、指定对应字段的约束条件 extra_kwargs ,注意 ⚠️ :不是model中的,不可以在extra_kwargs 做限制
extra_kwargs = { 'leader':{ "write_only":True, "max_length":200, } }
使用View获取视图数据
from django.views import View
1、如果返回的是数据集,要添加many=True,一条数据,直接传入就可以
2、序列化,传instance, 反序列化data
3、JsonResponse第一个默认参数是字典,如果不是要加JsonResponse(serializer.data,safe=False)
4、校验输入的数据
a、用序列化器对象的is_valid方法,才开始校验前端参数(校验成功返回true,错误返回False),raise_exception=True校验失败后会报出异常
b、调用is_valid之后才会调用errors。获取校验的提示(字典)
c、获取校验成功后的数据,可使用validated_data获取
5、如果一个序列化器传值 ProjectSerializer(instance=project, data=python_data)
a、只给一个data传值时,那么只会调用save(),就会调用create()
b、只给一个instance传值时,那么只会调用save(),就会调用update()
c、同时传两个值,会调用update()和create()
6、JsonResponse第一个默认参数是字典,如果不是要加JsonResponse(serializer.data,safe=False)
data = { 'name': "郭靖django", 'sex': '男性', 'dsc': 'django射雕英雄传人物', 'hbook_id': 1 } serializer = HeroInfoSerializer(data=data) serializer.is_valid() serializer.is_valid(raise_exception=True) serializer.errors serializer.validated_data serializer.save()
三、视图
前提:使用Django中的View,实现增删改查(序列化)
import json from django.views import View from DRF_Learn.models import Book from django.http import JsonResponse, HttpResponse class BookListView(View): def get(self, request): books = Book.objects.all() book_list = [] for book in books: book_dict = { 'id': book.id, 'name': book.name, 'author': book.author, 'date_time': book.date_time } book_list.append(book_dict) return JsonResponse(book_list, safe=False) def post(self, request): book_dict = json.loads(request.body.decode()) book = Book( name=book_dict['name'], author=book_dict['author'], date_time=book_dict['date_time'] ) book.save() book_dict = { 'id': book.id, 'name': book.name, 'author': book.author, 'date_time': book.date_time } return JsonResponse(book_dict) class BookDetailView(View): def get(self, request, pk): try: book = Book.objects.get(pk=pk) except Book.DoesNotExist: return HttpResponse({'message': "无数据"}, status=404) book_dict = { 'id': book.id, 'name': book.name, 'author': book.author, 'date_time': book.date_time } return JsonResponse(book_dict) def put(self, request, pk): try: book = Book.objects.get(pk=pk) except Book.DoesNotExist: return HttpResponse({'message': "无数据"}, status=404) book_dict = json.loads(request.body.decode()) book.name = book_dict['name'] book.author = book_dict['author'] book.date_time = book_dict['date_time'] book.save() book_dict = { "id": book.id, "name": book.name, "author": book.author, "date_time": book.date_time } return JsonResponse(book_dict) def delete(self, request, pk): try: book = Book.objects.get(pk=pk) except Book.DoesNotExist: return HttpResponse({'message': "无数据"}, status=404) book.delete() return HttpResponse(status=202)
无序列化、视图View —> 增加序列化(Serializer,ModelSerializer),视图View —> 视图进阶为APIView —> 视图进阶为GenericAPIView —> GenericAPIView + Mixin合成类 —> ViewSet合并详情视图和List视图 —> GenericViewSet合并统一 —> 视图集(ReadOnlyModelViewSet、ModelViewSet)
1、View视图
serializer = HeroInfoSerializer(data=data) serializer.is_valid() # 校验 serializer.is_valid(raise_exception=True) serializer.error # 获取错误信息 serializer.validated_data # 获取处理后数据 serializer.save() # 调用增加或者更新方法
2、视图进阶为APIView
这时增加APIView,我们可以主要增加了获取数据request.data
,获取参数request.query_params。在返回数据增加了Response
。获取序列化后的数据使用serializer.data
,状态新增了status。
from rest_framework.views import APIView, Response, status data = request.data serializer = BookInfoSerializer(data=data) Response(serializer.data)
3、视图进阶为GenericAPIView
主要增加了获取数据集和序列化
指定数据集和序列化
queryset = Book.objects.all()
serializer_class = BookInfoSerializer
获取数据集和序列化
self.get_queryset() 获取全数据集
self.get_object() 获取单一数据集
self.get_serializer 获取指定的序列化
4、GenericAPIView + Mixin合成类
<1>、继承ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin 完成增删改查
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, \ UpdateModelMixin class BookListGenericAPIView(ListModelMixin, CreateModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookInfoSerializer def get(self, request): # instance = self.get_queryset() # serializer = self.get_serializer(instance, many=True) return self.list(request) def post(self, request): return self.create(request) class BookDetailGenericAPIView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookInfoSerializer def get(self, request, pk): # instance = self.get_object() # serializer = self.get_serializer(instance) return self.retrieve(request, pk) def put(self, request, pk): return self.update(request, pk) def delete(self, request, pk): return self.destroy(request, pk)
<2>、继承ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin完成增删改查
备注:这里继承的类中直接定义了get、post、put、delete所以可以不用再重新编辑方法。实际还是继承了ModelMixin的方法,所以要制定查询集和序列化器
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, \ UpdateModelMixin class BookListGenericAPIView(ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookInfoSerializer class BookDetailGenericAPIView(RetrieveUpdateDestroyAPIView): queryset = Book.objects.all() serializer_class = BookInfoSerializer
5、视图集
视图集
1、为了将???ListView和???DetailView两个方法写到一个类中,由于as_view指定路由时根据get和post等小写名来进行关联所以无法将这两类写到一个类中。
2、ViewSet视图集通过改变as_view的路由方式,创建了list、retrieve、destroy、put、create行为来重新做了定义。来实现写到一个类中。
一、定义路由
urlpatterns = [ # 视图集路由 path('', views.BookListGenericViewSet.as_view({'get': 'list', 'post': 'create'})), path('<int:pk>/', views.BookListGenericViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})) ]
二、ViewSet
ViewSet视图集是继承APIView。
from rest_framework.viewsets import ViewSet, GenericViewSet from .serializers import BookInfoSerializer from rest_framework.response import Response from .models import Book class BookListGenericViewSet(ViewSet): def list(self, request): instance = Book.objects.all() serializer = BookInfoSerializer(instance, many=True) return Response(serializer.data) def create(self, request): data = request.data serializer = BookInfoSerializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) class BookDetailGenericViewSet(ViewSet): def retrieve(self, request, pk): instance = Book.objects.get(id=pk) serialzier = BookInfoSerializer(instance) return Response(serialzier.data) def update(self, request, pk): instance = Book.objects.get(id=pk) data = request.data serializer = BookInfoSerializer(instance=instance, data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) def destroy(self, request, pk): instance = Book.objects.get(id=pk) instance.delete() return Response({'message': "删除成功"})
三、GenericViewSet
GenericViewSet继承GenericAPIView.
from rest_framework.viewsets import ViewSet, GenericViewSet from .serializers import BookInfoSerializer from rest_framework.response import Response from .models import Book class BookListGenericViewSet(GenericViewSet): queryset = Book.objects.all() serializer_class = BookInfoSerializer def list(self, request): instance = self.get_queryset() serializer = self.get_serializer(instance, many=True) return Response(serializer.data) def create(self, request): data = request.data serializer = self.get_serializer(data=data) serializer.is_valid() serializer.save() return Response(serializer.data) class BookDetailGenericViewSet(GenericViewSet): queryset = Book.objects.all() serializer_class = BookInfoSerializer def retrieve(self, request, pk): instance = self.get_object() serializer = BookInfoSerializer(instance=instance) return Response(serializer.data) def update(self, request, pk): instance = self.get_object() data = request.data serializer = self.get_serializer(instance, data) serializer.is_valid() serializer.save() return Response(serializer.data) def destroy(self, request, pk): instance = self.get_object() instance.delete() return Response({'message': '删除成功'})
四、ReadOnlyModelViewSet
继承了RetrieveModelMixin、ListModelMixin、GenericViewSet。拥有了查单一和查所有的功能。
ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
五、ModelViewSet
继承了CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin、ListModelMixin、GenericViewSet。拥有了增删改查的功能。
ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet)
六、优化路由
历史:
from django.urls import path from DRF_Learn import views urlpatterns = [ # 视图集ModelViewSet路由 path('', views.BookViewSet.as_view({'get': 'list', 'post': 'create'})), path('<int:pk>/', views.BookViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})) ]
简化版:
from DRF_Learn import views from rest_framework.routers import DefaultRouter urlpatterns = [] router = DefaultRouter() # 创建路由 router.register(r'', views.BookViewSet) # 注册路由 router.register(r'hero/', views.HeroViewSet) # 注册路由 urlpatterns += router.urls # 把生成好的路由拼接到urlpatterns
视图集
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from .models import Book, Hero from .serializers import BookInfoSerializer, HeroInfoSerializer class BookViewSet(ModelViewSet): queryset = Book.objects.all() serializer_class = BookInfoSerializer class HeroViewSet(ReadOnlyModelViewSet): queryset = Hero.objects.all() serializer_class = HeroInfoSerializer
HTTPResponse、JSONResponse和Response运用场景
HTTPResponse:
是由Django创造的,他的返回格式为:
HTTPResponse(content=响应体,content_type=响应体数据类型,status=状态码)、可以修改返回的数据类型,适用于返回图片,视频,音频等二进制文件。
JSONResponse:
JSONResponse是HTTPResponse的子类,适用于处理json格式的数据,但是不能返回模板。帮助我们将数据转换为json字符串、设置响应头Content-Type为application/json。
Response:
是Django rest-framework框架中封装好的响应对象。它的返回格式为:
Response(data,status=None,template_name=None,headers=None,content_type=None),data只需传递Python的内建类型数据即可,如果是Django的模型类对象,那么就是用序列化数据(Python的字典数据)传递给data。
render和redirect:
render 返回页面内容(渲染变量到模板中),并且没有发送第二次请求
redirect 发送了第二次请求,是个跳转函数,一般跳转到外部网站,而且会返回302的状态码
此外:
- render 参数一般为模板html文件
- redirect 参数一般为URL地址