RESTful¶
web应用模式¶
1.前后端不分离¶
在**前后端不分离**的应用模式中,前端页面**看到的效果都是**由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的**耦合度很高**。
这种应用模式**比较适合纯网页**应用,但是当后端对接App时,App可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不再适用于前端App应用,为了对接App后端还需再开发一套接口。
2.前后端分离¶
在前后端分离的应用模式中,后端仅返回前端所需的数据,不再渲染HTML页面,不再控制前端的效果。至于前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页的处理方式,App有App的处理方式,但无论哪种前端,所需的数据基本相同,后端仅需开发一套逻辑对外提供数据即可。
在前后端分离的应用模式中 ,前端与后端的耦合度相对较低。我们通常将后端开发的每个视图都称为一个**接口**,或者**API**,前端通过访问接口来对数据进行增删改查。
认识RESTful¶
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。
非REST的url:http://.../queryGoods?id=1001&type=t01
REST的url:http://.../t01/goods/1001
REST特点:url简洁,将参数通过url传到服务器
RESTful设计思想¶
请求¶
1.域名
应该尽量将API部署在专用域名之下。
2.版本
3.路径
4.HTTP动词
5.过滤信息
响应¶
1.状态码
2.错误处理
3.返回结果
4.返回的格式
Django****开发****REST 接口¶
- 将请求的数据(如JSON格式)转换为模型类对象**(反序列化)**
- 操作数据库
- 将模型类对象转换为响应的数据(如JSON格式)(序列化)
明确****REST****接口开发的核心任务¶
序列化:****Django中的模型对象转换为JSON字符串
反序列化:****JSON字符串转换为Django中的模型类对象
1.在开发REST API接口时,我们在**视图**中需要做的最核心的事是:
- 将前端发送的数据反序列化为模型类对象,并保存到数据库中。
- 将数据库数据序列化为前端所需要的格式,并返回;
Django REST framework 简介¶
开发REST API¶
- 增:校验请求数据 -> 执行反序列化过程 ->保存数据库 ->将保存的对象序列化并返回
- 删:判断要删除的数据是否存在 -> 执行数据库删除
- 改:判断要修改的数据是否存在 ->校验请求的数据 -> 执行反序列化过程 ->保存数据库 ->将保存的对象序列化并返回
- 查:查询数据库 -> 将数据序列化并返回
特点¶
- 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
- 提供了丰富的类视图、Mixin扩展类,简化视图的编写;
- 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
- 多种身份认证和权限认证方式的支持;
- 内置了限流系统;
- 直观的 API web 界面;
- 可扩展性,插件丰富
使用步骤¶
1.安装
pip install djangorestframework
2.注册子应用
INSTALLED_APPS = [
...
'rest_framework',
]
为什么要用DRF¶
Django中用JsonResponse开发API需要根据用户请求信息构建字典格式数据内容,这种方式开发API很容易造成代码冗余,不利于功能的变更和维护。
为了简化API的开发过程,我们可以使用Django Rest Framework框架实现API开发。使用框架开发不仅能减少代码冗余,还可以规范代码的编写格式,这对企业级开发来说很有必要,毕竟每个开发人员的编程风格存在一定的差异,开发规范化可以方便其他开发人员查看和修改。
DRF使用流程¶
- 先用定义Django原生models
- 序列化(serializers)
- 视图集(业务逻辑)
- 在子路由注册视图集
- 在总路由注册
序列化和反序列化¶
Serializers字段和选项¶
1.定义Serializer类¶
from rest_framework import serializers
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
**serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。**serializer是独立于数据库之外的存在。
2.字段与选项¶
字段 | 字段构造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField(format='hex_verbose') format: 1)'hex_verbose'如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2)'hex'如"5ce0e9a55ffa654bcee01238041fb31a" 3)'int'- 如:"123456789012312313134124512351145145114" 4)'urn'如:"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
IPAddressField | IPAddressField(protocol='both', unpack_ipv4=False, **options) |
IntegerField | IntegerField(max_value=None, min_value=None) |
FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
DurationField | DurationField() |
ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
MultipleChoiceField | MultipleChoiceField(choices) |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ListField | ListField(child=, min_length=None, max_length=None) |
DictField | DictField(child=) |
通用参数:
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
required | 表明该字段在反序列化时必须输入,默认False |
default | 反序列化时使用的默认值 |
label | 用于HTML展示API页面时,显示的字段名称 |
选项参数:
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_lenght | 最小长度 |
allow_blank | 是否允许为空 |
max_value | 最大值 |
min_value | 最小值 |
3.创建Serializer对象¶
# Serializer的构造方法为
Serializer(instance=None,data=empty,**kwarg)
# 1.用于序列化时,将模型类对象传入instance参数
serializer = BookInfoSerializer(instance=book)
#或者
serializer = BookInfoSerializer(book)
# 2.用于反序列化时,将要被反序列化的数据传入data参数
serializer = BookInfoSerializer(data={'name':'xxxx','pub_date':'2000-01-10'})
序列化(响应、后端返回JSON给前端)¶
基本使用¶
# 1.先查出一个图书对象
from learning.books.models import BookInfo
book = BookInfo.objects.get(id=4)
# 2.构造序列化器对象
from learning.books.serializer import BookInfoSerializer
serializer = BookInfoSerializer(book) # 传递模型实例
# 3.获取序列化数据(对象转换为字典的数据)
serializer.data
{'id': 4, 'name': '雪山飞狐', 'pub_date': '1987-11-11', 'readcount': 58, 'commentcount': 24}
# 4.如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明
b = BookInfo.objects.all()
s = BookInfoSerializer(b,many=True) # 如果模型返回列表,设置many=True
s.data
[{'id': 1, 'name': '射雕英雄传put修改', 'pub_date': '1980-05-01', 'readcount': 12, 'commentcount': 34}, {'id': 2, 'name': '天龙八部', 'pub_date': '1986-07-24', 'readcount': 36, 'commentcount': 40}, {'id': 3, 'name': '笑傲江湖', 'pub_date': '1995-12-24', 'readcount': 20, 'commentcount': 80}, {'id': 4, 'name': '雪山飞狐', 'pub_date': '1987-11-11', 'readcount': 58, 'commentcount': 24}]
关联对象嵌套序列化¶
1.IntegerField¶
class PeopleInfoSerializer(serializers.Serializer):
# 根据表字段来获取外键
# 此字段将被序列化为关联对象的主键。
book_id = serializers.IntegerField(label='书籍ID')
from learning.books.models import PeopleInfo
from learning.books.serializer import PeopleInfoSerializer
person = PeopleInfo.objects.get(id=10)
serializer = PeopleInfoSerializer(person)
serializer.data
{'id': 10, 'name': '令狐冲', 'password': '123456abc', 'description': '独孤九剑', 'book_id': 3, 'is_delete': False}
2.PrimaryKeyRelatedField¶
class PeopleInfoSerializer(serializers.Serializer):
# 此字段将被序列化为关联对象的主键
# 包含read_only=True参数时,该字段将不能用作反序列化使用
# 包含queryset参数时,将被用作反序列化时参数校验使用
book = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)
# 或
# book = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())
p = PeopleInfo.objects.get(id=10)
s = PeopleInfoSerializer(instance=p)
s.data
{'id': 10, 'name': '令狐冲', 'password': '123456abc', 'description': '独孤九剑', 'book': 3}
3.StringRelatedField¶
此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)
class BookInfo(models.Model):
pass
def __str__(self):
"""定义每个数据对象的显示信息"""
return "BookInfo" + self.name
class PeopleInfoSerializer(serializers.Serializer):
book = serializers.StringRelatedField(label='图书')
from learning.books.models import PeopleInfo
from learning.books.serializer import PeopleInfoSerializer
p = PeopleInfo.objects.get(id=10)
s = PeopleInfoSerializer(p)
{'id': 10, 'name': '令狐冲', 'password': '123456abc', 'description': '独孤九剑', 'book': 'BookInfo笑傲江湖'}
4.使用关联对象的序列化器¶
from rest_framework import serializers
class PeopleInfoSerializer(serializers.Serializer):
pass
class BookInfoSerializer(serializers.Serializer):
#一本书籍关联多个人物
people=PeopleInfoSerializer(many=True)
from learning.books.models import BookInfo
from learning.books.serializer import BookInfoSerializer
b = BookInfo.objects.get(id=1)
s = BookInfoSerializer(b)
s.data
{'id': 1, 'name': '射雕英雄传put修改', 'pub_date': '1980-05-01', 'readcount': 12, 'commentcount': 34, 'people': [{'id': 1, 'name': '郭靖', 'password': '123456abc', 'description': '降龙十八掌'}, {'id': 2, 'name': '黄蓉', 'password': '123456abc', 'description': '打狗棍法'}, {'id': 3, 'name': '黄药师', 'password': '123456abc', 'description': '弹指神通'}, {'id': 4, 'name': '欧阳锋', 'password': '123456abc', 'description': '蛤蟆功'}, {'id': 5, 'name': '梅超风', 'password': '123456abc', 'description': '九阴白骨爪'}]}
反序列化(请求--前端传给后端的)¶
1.验证¶
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用**is_valid()**方法进行验证,验证成功返回True,否则返回False。
验证失败,可以通过序列化器对象的**errors**属性获取错误信息,返回字典,包含了字段和字段的错误。
验证成功,可以通过序列化器对象的**validated_data**属性获取数据。
# 在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID')
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 验证is_valid() 为False
from learning.books.serializer import BookInfoSerializer
data = {
'name':'Python高级',
'pub_date':'2020-1-1',
'readcount':100,
'commentcount':200}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
False
serializer.errors
{'id': [ErrorDetail(string='该字段是必填项。', code='required')]}
# 验证is_valid() 为True
from learning.books.serializer import BookInfoSerializer
data = {
'id':100,
'name':'Python高级',
'pub_date':'2020-1-1',
'readcount':100,
'commentcount':200}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
True
serializer.errors
{}
1.字段类型
is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID')
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 失败时抛出异常
from learning.books.serializer import BookInfoSerializer
data = {
'id':100,
'name':'Python高级',
'pub_date':'2020',
'readcount':100,
'commentcount':200}
s = BookInfoSerializer(data=data)
s.is_valid(raise_exception=True)
False
s.errors
{'pub_date': [ErrorDetail(string='日期格式错误。请从这些格式中选择:YYYY-MM-DD。', code='invalid')]}
2.字段选项
read_only
# 像id这样的主键值,一般我们都是让数据库自动生成,所以一般不会传入。则需要设置为 read_only
id = serializers.IntegerField(label='ID',read_only=True)
write_only
# 只写入。我们在进行反序列化的时候,必须要求传入该字段。在进行序列化操作的时候不会获取到该字段的值。
password = serializers.IntegerField(label='密码',read_only=True)
read_only=True
write_only=True
id = serializers.IntegerField(label='ID',read_only=True) 表明该字段仅用于序列化输出 password = serializers.IntegerField(label='ID',write_only=True) 表明该字段仅用于反序列化输入
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID')
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 验证is_valid() 为False
from learning.books.serializer import BookInfoSerializer
data = {
'name':'Python高级',
'pub_date':'2020-1-1',
'readcount':100,
'commentcount':200}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
False
serializer.errors
{'id': [ErrorDetail(string='该字段是必填项。', code='required')]}
3.validate_fieldname(字段名)
class BookInfoSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 需求数据获取书籍以及书籍关联的人物
# 一本书籍关联多个人物
people = PeopleInfoSerializer(many=True, read_only=True)
def validate_readcount(self, value):
"""
对<field_name>字段进行验证
"""
if value < 0:
raise serializers.ValidationError('阅读数量不能为负数')
return value
from learning.books.serializer import BookInfoSerializer
data = {'name':'python高级','pub_date':'2021-01-01','readcount':-100,'commentcount':200}
s = BookInfoSerializer(data=data)
s.is_valid(raise_exception=True)
# 报错
Traceback (most recent call last):
File "C:\Program Files\JetBrains\PyCharm 2023.2.4\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode
coro = func()
File "<input>", line 1, in <module>
File "C:\Users\50599\Desktop\start\lib\site-packages\rest_framework\serializers.py", line 231, in is_valid
raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'readcount': [ErrorDetail(string='阅读数量不能为负数', code='invalid')]}
4.validate
在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证
class BookInfoSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 需求数据获取书籍以及书籍关联的人物
# 一本书籍关联多个人物
people = PeopleInfoSerializer(many=True, read_only=True)
def validate(self, attrs):
readcont = attrs['readcont']
commentcount = attrs['commentcount']
if commentcount > readcont:
raise serializers.ValidationError('评论量不能大于阅读量')
return attrs
from learning.books.serializer import BookInfoSerializer
data = {
'name':'Python高级',
'pub_date':'2020-01-01',
'readcount':100,
'commentcount':200}
s = BookInfoSerializer(data=data)
s.is_valid(raise_exception=True)
Traceback (most recent call last):
File "C:\Program Files\JetBrains\PyCharm 2023.2.4\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode
coro = func()
File "<input>", line 8, in <module>
File "C:\Users\50599\Desktop\start\lib\site-packages\rest_framework\serializers.py", line 231, in is_valid
raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'non_field_errors': [ErrorDetail(string='评论量不能大于阅读量', code='invalid')]}
2.保存¶
如果在验证成功后,想要基于validated_data完成数据对象的创建,可以通过实现create()和update()两个方法来实现。
class BookInfoSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 需求数据获取书籍以及书籍关联的人物
# 一本书籍关联多个人物
people = PeopleInfoSerializer(many=True, read_only=True)
# def validate_readcount(self, value):
# """对<field_name>字段进行验证"""
# if value < 0:
# raise serializers.ValidationError('阅读数量不能为负数')
# return value
def validate(self, attrs):
readcount = attrs['readcount']
commentcount = attrs['commentcount']
if commentcount > readcount:
raise serializers.ValidationError('评论量不能大于阅读量')
return attrs
def create(self, validated_data):
return BookInfo.objects.create(**validated_data)
# 验证
from learning.books.serializer import BookInfoSerializer
data = {
'name':'Python高级',
'pub_date':'2020-01-01',
'readcount':1000,
'commentcount':200}
# serializer 名字不能改
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
True
serializer.save()
<BookInfo: BookInfoPython高级1>
class BookInfoSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称')
pub_date = serializers.DateField(label='发布日期')
readcount = serializers.IntegerField(label='阅读量')
commentcount = serializers.IntegerField(label='评论量')
# 需求数据获取书籍以及书籍关联的人物
# 一本书籍关联多个人物
people = PeopleInfoSerializer(many=True, read_only=True)
def validate(self, attrs):
readcount = attrs['readcount']
commentcount = attrs['commentcount']
if commentcount > readcount:
raise serializers.ValidationError('评论量不能大于阅读量')
return attrs
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.pub_date = validated_data.get('pub_date', instance.pub_date)
instance.readcount = validated_data.get('readcount', instance.readcount)
instance.commentcount = validated_data.get('commentcount', instance.commentcount)
instance.save()
return instance
# 验证
from learning.books.models import BookInfo
from learning.books.serializer import BookInfoSerializer
b = BookInfo.objects.get(id=1)
data = {
'name':'Python高级4',
'pub_date':'2020-01-01',
'readcount':1000,
'commentcount':200}
serailizer = BookInfoSerializer(instance=b,data=data,partial=True)
serailizer.is_valid(raise_exception=True)
serailizer.save()
模型类序列化器ModelSerializer¶
from learning.books.models import BookInfo
from rest_framework import serializers
class BookInfoModelSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo # 指明参照那个模型类
fields = '__all__' # 添加的字段 all 表示全部
# fields = ('name', 'readcount') # 添加部分字段
# exclude = ('image',) # 排除字段
read_only_fields = ('id', 'name') # 指明只读字段,仅用于序列化输出的字段
# 使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
extra_kwargs = {
'readcount': {'min_value': 0, 'required': False}, # required 表明该字段在反序列化时必须输入默认
'commentcount': {'max_value': 0, 'required': True},
}
进阶使用¶
1.保存1个人物信息¶
# body1
data = {
'book':1,
'name': '靖哥哥',
'password': '123456abc',
}
class PeopleInfoModelSerializer(serializers.ModelSerializer):class Meta:
model = PeopleInfo
fields = ['id','book','name','password']
extra_kwargs = {
'password': {'write_only':True}
}
# write_only表明该字段仅用于反序列化输入。在序列化输出时忽略该字段。
# body2
data = {
'book_id':1,
'name': '靖哥哥',
'password': '123456abc'
}
from rest_framework import serializers
from book.models import PeopleInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','name','password']
extra_kwargs = {
'password': {'write_only':True}
}
# 或者
from rest_framework import serializers
from book.models import PeopleInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField(required=False)
book=serializers.StringRelatedField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','book','name','password']
extra_kwargs = {
'password': {'write_only':True}
}
# 外键book或者book_id都可以保存数据。主要看前端传递过来的数据形式
# body3
data = {
'book_id':1,
'name': '靖哥哥',
'password': '123456abc',
'is_delete': 1
}
from rest_framework import serializers
from book.models import PeopleInfo,BookInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField(required=False)
book=serializers.StringRelatedField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','book','name','password','is_delete']
extra_kwargs = {
'password': {'write_only':True},
'is_delete': {'read_only':True}
}
# read_only表明该字段仅用于序列化输出。反序列化时忽略次字段。
# body4
data = {
'book_id':1,
'name': '靖哥哥',
'password': '123456abc',
'description': '描述',
'is_delete': 1
}
from rest_framework import serializers
from book.models import PeopleInfo,BookInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField(required=False)
book=serializers.StringRelatedField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','book','name','password','is_delete']
extra_kwargs = {
'password': {'write_only':True},
'is_delete': {'read_only':True}
}
# description没有在序列化器中定义字段。如果需要验证或保存某一个字段是必须要在序列化器中定义该字段
2.保存n个人物信息¶
# body5
[
{
'book_id': 1,
'name': '靖妹妹~~~',
'password':'123456abc'
},
{
'book_id': 1,
'name': '靖表哥~~~',
'password': '123456abc'
}
]
from rest_framework import serializers
from book.models import PeopleInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField(required=False)
book=serializers.StringRelatedField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','book','name','password','is_delete']
extra_kwargs = {
'password': {'write_only':True},
'is_delete': {'read_only':True}
}
# 进行反序列化也可以保存字典列表,需要设置many=True
3.保存1本新书籍和n个新人物信息¶
Serializer relations - Django REST framework
{
'name':'离离原上草',
'people':[
{
'name': '靖妹妹111',
'password': '123456abc'
},
{
'name': '靖表哥222',
'password': '123456abc'
}
]
}
from rest_framework import serializers
from book.models import PeopleInfo,BookInfo
class PeopleInfoModelSerializer(serializers.ModelSerializer):
book_id=serializers.IntegerField(required=False)
book=serializers.StringRelatedField()
class Meta:
model = PeopleInfo
fields = ['id','book_id','book','name','password','is_delete']
extra_kwargs = {
'password': {'write_only':True},
'is_delete': {'read_only':True}
}
class BookInfoModelSerializer(serializers.ModelSerializer):
people=PeopleInfoModelSerializer(many=True)
class Meta:
model = BookInfo
fields = '__all__'def create(self, validated_data):
people=validated_data.pop('people')
book=BookInfo.objects.create(**validated_data)
for person in people:
PeopleInfo.objects.create(book=book,**person)
return book
# 默认情况下,嵌套串行器是只读的。如果要支持对嵌套序列化器字段的写操作,则需要创建create()或update()方法,以明确指定应如何保存数据。
视图¶
1.Request与Response¶
1.Request¶
from rest_framework.request import Request
# REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。
# Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。
常用属性¶
01.data¶
request.data
返回解析之后的请求体数据。类似于Django中标准的request.POST
属性,但提供如下特性:
- 包含了对POST、PUT、PATCH请求方式解析后的数据
- 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
# 源码
from rest_framework.request import Request
class Request:
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
def _load_data_and_files(self):
"""
Parses the request content into `self.data`.
"""
if not _hasattr(self, '_data'):
self._data, self._files = self._parse()
if self._files:
self._full_data = self._data.copy()
self._full_data.update(self._files)
else:
self._full_data = self._data
# if a form media type, copy data & files refs to the underlying
# http request so that closable objects are handled appropriately.
if is_form_media_type(self.content_type):
self._request._post = self.POST
self._request._files = self.FILES
02.query_params¶
request.query_params
与Django标准的request.GET
相同。
from rest_framework.request import Request
class Request:
@property
def query_params(self):
"""
More semantically correct name for request.GET.
"""
return self._request.GET
2.Response¶
REST framework提供了
Renderer
渲染器,用来根据请求头中的Accept
(接收数据类型声明)来自动转换响应数据到对应格式。如果前**端请求中未进行Accept声明,则会采用默认方式处理响应数据**,我们可以通过配置来修改默认响应格式。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
1.构造方式¶
Response(data, status=None, template_name=None, headers=None, content_type=None)
"""
data只需传递python的内建类型数据即可。
data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。
data: 为响应准备的序列化处理后的数据;
status: 状态码,默认200;
template_name: 模板名称,如果使用HTMLRenderer时需指明;
headers: 用于存放响应头信息的字典;
content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
"""
2.状态码¶
1)信息告知 - 1xx¶
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2)成功 - 2xx¶
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3)重定向 - 3xx¶
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY 永久重定向
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4)客户端错误 - 4xx¶
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5)服务器错误 - 5xx¶
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
2.视图¶
1.APIView(一级)¶
from django.views.generic.base import View
from rest_framework.views import APIView
# APIView继承自Django中View
"""
APIView与View的不同之处在于:
传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
任何APIException异常都会被捕获到,并且处理成合适的响应信息;
在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性:
authentication_classes列表或元祖,身份认证类
permissoin_classes列表或元祖,权限检查类
throttle_classes列表或元祖,流量控制类
"""
from django.views.generic.base import View
from rest_framework.views import APIView
from learning.books.models import BookInfo
from learning.books.modelserializer import BookInfoModelSerializer
from rest_framework.response import Response
class BookListApiView(APIView):
def get(self, request):
# 1.查询数据
books = BookInfo.objects.all()
# 2.创建序列化器,并传递查询结果集(如果是列表设置many=True)
serializer = BookInfoModelSerializer(books, many=True)
# 3.返回响应 Serializer.data
return Response(serializer.data) # 列表套字典
def post(self, request):
# 1.接受参数
book_dict = request.data
# 2.创建序列化器,并传递参数
serializer = BookInfoModelSerializer(data=book_dict)
# 3.验证数据,并根据验证结果进行判断
if serializer.is_valid():
# 4.验证数据没有问题,调用序列化器的save方法。来触发序列化器的create方法,create方法会调用模型来保存到数据库中
serializer.save()
# 5.返回响应 Serializer.data 就是字典数据
return Response(serializer.data)
else:
# 数据验证有问题,返回错误信息
msg = serializer.errors
return Response({'msg': f'{msg}'})
2.GenericAPIView(二级)¶
继承自
APIVIew
,增加了对于**列表视图**和**详情视图**可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
属性¶
- 列表详情视图通用
- **queryset**列表视图的查询集
- **serializer_class**视图使用的序列化器
- 详情页视图使用
- **lookup_field**查询单一数据库对象时使用的条件字段,默认为'
pk
' - **lookup_url_kwarg**查询单一数据时URL中的参数关键字名称,默认与**look_field**相同
方法¶
- 列表详情视图通用
get_queryset(self)
返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回
queryset
属性,可以重写,例如:
def get_queryset(self):
return BookInfo.objects.all()
get_serializer_class(self)
返回序列化器类,默认返回
serializer_class
,可以重写,例如:
def get_serializer_class(self):
return BookInfoModelSerializer
get_serializer(self,_args, *_kwargs)
返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。注意,在提供序列化器对象的时候,****REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
- 详情页视图使用
get_object(self)
返回详情视图所需的模型类数据对象,默认使用
lookup_field
参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。若详情访问的模型类对象不存在,会返回404。
3.MIxin¶
0**1.ListModelMixin**¶
列表视图扩展类,提供
list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。
# 源码
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
02.CreateModelMixin¶
创建视图扩展类,提供
create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
# 源码
class CreateModelMixin:
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
03.RetrieveModelMixin¶
详情视图扩展类,提供
retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
# 源码
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
04.UpdateModelMixin¶
更新视图扩展类,提供
update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。同时也提供
partial_update(request, *args, **kwargs)
方法,可以实现局部更新。成功返回200,序列化器校验数据失败时,返回400错误。
class UpdateModelMixin:
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
05.DestroyModelMixin¶
删除视图扩展类,提供
destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
class DestroyModelMixin:
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
demo¶
class BookListGenericMixinView(ListModelMixin, CreateModelMixin,
GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化属性
serializer_class = BookInfoModelSerializer
def get(self, request):
"""调用Mixin的list方法"""
return self.list(request)
def post(self, request):
"""调用Mixin的create方法"""
return self.create(request)
class BookListGenericMixinViews(UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化属性
serializer_class = BookInfoModelSerializer
def get(self, request, pk):
"""调用Mixin的retrieve方法"""
return self.retrieve(request)
def put(self, request, pk):
"""调用Mixin的update的方法"""
return self.update(request)
def delete(self, request, pk):
"""调用Mixin的destory的方法"""
return self.destroy(request)
4.子类视图(三级)¶
1) CreateAPIView¶
from rest_framework.generics import CreateAPIView
"""
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
"""
2)ListAPIView¶
from rest_framework.generics import ListAPIView
"""
提供 get 方法
继承自:GenericAPIView、ListModelMixin
"""
3)RetireveAPIView¶
from rest_framework.generics import RetrieveAPIView
"""
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
"""
4)DestoryAPIView¶
from rest_framework.generics import DestroyAPIView
"""
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
"""
5)UpdateAPIView¶
from rest_framework.generics import UpdateAPIView
"""
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
"""
6)RetrieveUpdateAPIView¶
from rest_framework.generics import RetrieveUpdateAPIView
"""
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
"""
7)RetrieveUpdateDestoryAPIView¶
from rest_framework.generics import RetrieveUpdateDestroyAPIView
"""
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
"""
3.视图集ViewSet¶
Viewsets - Django REST framework
视图集操作
REST 框架中包含的默认路由器将为一组标准的创建/检索/更新/销毁样式操作提供路由,如下所示:
class UserViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""
def list(self, request):
"""
查所有
"""
pass
def create(self, request):
"""
增
"""
pass
def retrieve(self, request, pk=None):
"""
查某一个
"""
pass
def update(self, request, pk=None):
"""
改全部
"""
pass
def partial_update(self, request, pk=None):
"""
改部分
"""
pass
def destroy(self, request, pk=None):
"""
删
"""
pass
使用
ViewSet
类比使用View
类有两个主要优点。
- 重复的逻辑可以合并成一个类。例如我们只需要指定
queryset
一次,它将用于多个视图。- 通过使用路由器,我们不再需要处理自己的URL配置
1.ViewSet¶
一个
ViewSet
类只是**一种基于类的View,**继承自APIView
,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。在ViewSet中,它不提供任何方法处理程序,需要我们自己重写该类并明确实现action方法。
在调度期间,以下属性在ViewSet
.
basename
用于创建的 URL 名称的基础。action
当前操作的名称(例如,list
,create
)。detail
布尔值,指示当前操作是否配置为列表视图或详细视图。suffix
视图集类型的显示后缀 - 镜像detail
属性。name
视图集的显示名称。这个论点与 是互斥的suffix
。description
视图集的各个视图的显示描述。
from rest_framework.viewsets import ViewSet
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from learning.books.modelserializer import BookInfoModelSerializer
from learning.books.models import BookInfo
class BookViewSet(ViewSet):
def list(self, request):
queryset = BookInfo.objects.all()
serializer = BookInfoModelSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = BookInfo.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = BookInfoModelSerializer(user)
return Response(serializer.data)
2.GenericViewSet¶
继承自
GenericAPIView
,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。在GenericAPIView
中,没有提供任何动作action方法,需要我们自己覆盖该类并混合所需的混合类,或者明确定义操作实现action方法
3.ModelViewSet¶
继承自
GenericAPIVIew
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
ModelViewSet
类所继承GenericAPIView
,包括用于各种动作实现方式中,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。由提供的动作
ModelViewSet
类是.list()
,.retrieve()
,.create()
,.update()
,.partial_update()
,和.destroy()
# 因为ModelViewSet扩展GenericAPIView,我们通常需要提供至少queryset和serializer_class属性
class BookViewSet(ViewSet, ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
4.ReadOnlyModelViewSet¶
继承自
GenericAPIVIew
,同时包括了ListModelMixin、RetrieveModelMixin。与
ModelViewSet
它一样,它还包括各种操作的实现,但不同于ModelViewSet
只提供“只读”操作,list()
而且retrieve()
4.路由Router¶
Routers - Django REST framework
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由列表信息。
REST framework提供了两个router
- SimpleRouter
- DefaultRouter
1.使用方法¶
# 1.创建router对象,并注册视图集
register(prefix, viewset,basename)
# prefix 该视图集的路由前缀
# viewset 视图集
# basename路由名称的前缀
from rest_framework import routers
router = routers.DefaultRouter()
router.register('books', BookViewSet, basename='book')
# 2.添加路由数据
# 方法一
urlpatterns = [
...
path('', include(router.urls))
]
# 方法二
urlpatterns = [
...
]
urlpatterns += router.urls
2.路由router形成URL的方式¶
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
drf-yasg¶
drf-yasg是一个Swagger / OpenAPI 2生成工具,无需使用 Django Rest Framework 提供的模式生成即可实现。
它的目标是尽可能多地实现OpenAPI 2规范 - 嵌套模式、命名模型、响应主体、枚举/模式/最小/最大验证器、表单参数等 - 并生成可与
swagger-codegen
.这也转化为一个非常有用的交互式文档查看器,其形式为
swagger-ui
:
使用方法¶
# 1.安装
pip install -U drf-yasg
# 2.注册
INSTALLED_APPS = [
...
'django.contrib.staticfiles', # required for serving swagger ui's css/js files
'drf_yasg',
...
]
# 3.总路由
# drf_yasg API
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Snippets API",
default_version='v1',
description="Test description",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="contact@snippets.local"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=[permissions.AllowAny],
)
urlpatterns = [
# drf_yasg API
# 这公开了 4 个端点
# API 规范的 JSON 视图,位于/swagger.json
# 您的 API 规范的 YAML 视图位于/swagger.yaml
path('swagger<format>/', schema_view.without_ui(cache_timeout=0), name='schema-json'),
# API 规范的 swagger-ui 视图位于/swagger/
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger - ui'),
# API 规范的 ReDoc 视图位于/redoc/
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
高级功能¶
1.认证Authentication¶
Authentication - Django REST framework
1.概念¶
身份验证是将传入请求与一组标识凭据(例如,请求来自的用户或与其进行签名的令牌)相关联的机制。然后,权限和限制策略可以使用这些凭据来确定是否应允许该请求。
身份验证本身不会允许或不允许传入的请求,它只会标识发出请求的凭据。
认证管理一般和权限管理配合使用。
2.认证方式¶
1.基本认证**(BasicAuthentication)**¶
此身份验证方案使用HTTP基本身份验证,该身份针对用户的用户名和密码进行了签名。基本身份验证通常仅适用于测试。
2.会话认证**(SessionAuthentication)**¶
此身份验证方案使用Django的默认会话后端进行身份验证。会话身份验证适用于在与您的网站相同的会话上下文中运行的****AJAX****客户端。
如果成功通过身份验证
request.user
将是DjangoUser
实例。未经授权的身份验证的响应将被拒绝
HTTP 403 Forbidden
。
3.令牌认证**(TokenAuthentication)**¶
此身份验证方案使用简单的基于令牌的HTTP身份验证方案。令牌认证适用于客户端-服务器设置,例如本机台式机和移动客户端。
为了使客户端进行身份验证,令牌密钥应包含在
Authorization
HTTP标头中。密钥应以字符串文字“ Token”作为前缀,并用空格分隔两个字符串。例如:
Authorization:Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
认证失败会有两种可能的返回值:
401 Unauthorized 未认证
403 Permission Denied 权限被禁止
3.认证全局设置¶
因为 认证一般都是和权限配合使用,当我们不设置权限时,是没有任何效果的。为了让大家看到最佳效果,我们额外添加一条配置信息。配置信息的意思是 只有认证登录用户才可以访问视图
REST_FRAMEWORK = {
# 默认的认证列表: session'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
# 默认的权限列表: 只有登录用户才可以访问'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
4.认证指定视图设置¶
from rest_framework.authentication import TokenAuthentication
class BookModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
#单个视图,设置单独认证方式
authentication_classes = [TokenAuthentication]
2.权限Permissions¶
Permissions - Django REST framework
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
- 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
- 在通过get_object()获取具体对象时,会进行对象访问权限的判断
1.提供的权限¶
- AllowAny 允许所有用户
- IsAuthenticated 仅通过认证的用户
- IsAdminUser 仅管理员用户
- IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
2.使用¶
# DRF 认证全局设置
REST_FRAMEWORK = {
# 默认的认证列表: session
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
# 默认的权限列表: 只有登录用户才可以访问
'DEFAULT_PERMISSION_CLASSES': (
# AllowAny 不指定默认 允许所有用户
# IsAuthenticated 仅通过认证的用户
# IsAdminUser 仅管理员用户
# IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
'rest_framework.permissions.IsAuthenticated',
)
}
# 或者
from rest_framework.authentication import TokenAuthentication
class BookModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
#单个视图,设置单独认证方式
authentication_classes = [SessionAuthentication]
3.指定视图设置¶
from rest_framework.permissions import AllowAny
class BookViewSet(ViewSet, ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
# 单个视图,设置单独认证方式
authentication_classes = [TokenAuthentication]
# 设置单独的权限
permission_classes = [AllowAny]
3.分页Pagination¶
Pagination - Django REST framework
# 全局设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10 # 每页数目
}
修改分页样式¶
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
# 修改配置文件
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
可选分页器¶
1)LimitOffsetPagination¶
可以在子类中定义的属性:
- default_limit 默认限制,默认值与
PAGE_SIZE
设置一致- limit_query_param limit参数名,默认'limit'
- offset_query_param offset参数名,默认'offset'
- max_limit 最大limit限制,默认None
http://127.0.0.1:8000/books/?limit=2&offset=4
class BookModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
#分页类
pagination_class = LimitOffsetPagination
2)PageNumberPagination¶
可以在子类中定义的属性:
- page_size 每页数目
- page_query_param 前端发送的页数关键字名,默认为"page"
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量
http://127.0.0.1:8000/books/?page=1&pagesize=4
#自定义分页类
class PageNum(PageNumberPagination):
page_size = 2 # 默认每页返回的条数
page_size_query_param = 'pagesize' # url中设置 page_size的键,默认为page_size
max_page_size = 10 # 每页返回的最大条数
class BookModelViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
#使用自定义分页类
pagination_class = PageNum