drf-day3
1. 知识回顾补充
回顾
1 2 3 4 5 6 7 8 9 10
| 1. request: 获取请求中所包含的参数 2. render: 决定了数据以何种的形式返回到前端 3. parser: 指定了视图可以接受前端传递什么类型的参数 4. 异常的处理: 解析了drf的异常时如何进行处理的 5. Response: 指定了响应请求的状态码 6. 序列化器: 将从数据库中查询的数据转换成json字符串来响应到前台 序列化: 自定义属性: SerializerMethodField自定义字段 反序列化: 将从前端获取的数据保存至数据库 对前端提交的数据进行安全校验 在保存对象时重写`create()`方法来完成对象的保存
|
钩子函数
在使用create()
方法去保存数据之前,可使用DRF提供的全局钩子以及局部钩子对数据进行自定义校验
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class EmployeeDeSerializer(serializers.Serializer): """ 反序列化: 将前端提交的数据保存到数据库 1. 需要前端提供哪些字段 2. 对字段进行安全校验 3. 有没有字段需要额外的校验 反序列化不需要自定义字段 """
username = serializers.CharField( max_length=3, min_length=2, error_messages={ "max_length": "长度太长了", "min_length": "长度太短了", } ) password = serializers.CharField() phone = serializers.CharField()
re_pwd = serializers.CharField()
def validate(self, attrs): pwd = attrs.get("password") re_pwd = attrs.pop("re_pwd")
if pwd != re_pwd: raise exceptions.ValidationError("两次密码不一致")
return attrs
def validate_username(self, value):
if "1" in value: raise exceptions.ValidationError("用户名有误")
emp = Employee.objects.filter(username=value) if emp: raise exceptions.ValidationError("用户名已存在")
return value
def create(self, validated_data): return Employee.objects.create(**validated_data)
|
2. 模型设计
表设计

抽象表(基表)
可以把多张表共有的字段抽取出来作为基表,
1 2 3 4 5 6 7 8 9 10
| class BaseModel(models.Model): is_delete = models.BooleanField(max_length=128) create_time = models.DateTimeField(auto_now_add=True) status = models.BooleanField(default=True)
class Meta: abstract = True
|
3. 序列化器之ModelSerializer
ModelSerializer使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class BookModelSerializer(serializers.ModelSerializer): class Meta: model = Book
exclude = ("is_delete", "status", "create_time")
|
ModelSerializer自定义字段
在序列化器要序列化的模型中提供类方法作为序列化器的自定义属性来展示
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
| class Book(BaseModel): book_name = models.CharField(max_length=128) price = models.DecimalField(max_digits=6, decimal_places=2) pic = models.ImageField(upload_to="img", default="img/1.jpg") publish = models.ForeignKey(to="Press", on_delete=models.CASCADE, db_constraint=False, related_name="books") authors = models.ManyToManyField(to="Author", db_constraint=False, related_name="books")
class Meta: db_table = "bz_book" verbose_name = "图书" verbose_name_plural = verbose_name
def __str__(self): return self.book_name
@property def press_name(self): return self.publish.press_name
@property def author_list(self): return self.authors.values("author_name", "age", "detail__phone")
|
序列化多表查询
- 序列化器嵌套夺表查询时, 必须指定的外键的名称,且需要早fields中使用它
- 如果嵌套的序列化器不是外键,则无法完成查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class PressModelSerializer(serializers.ModelSerializer): class Meta: model = Press fields = ("press_name", "pic", "address")
class BookModelSerializer(serializers.ModelSerializer):
publish = PressModelSerializer()
class Meta: model = Book
fields = ("book_name", "price", "pic", "publish")
|
4. ModelSerializer反序列化
反序列化器的定义
ModelSerializer
内部自己实现了create()
方法去保存对象, 无需开发者自己重写
extra_kwargs
: 可以通过此参数为反序列化器添加校验规则
全局钩子
与局部钩子
同样可以自定义校验规则
fields
中所标注的字段必须提供对应的值
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
| class BookDeModelSerializer(serializers.ModelSerializer): """反序列化器"""
class Meta: model = Book fields = ("book_name", "price", "publish", "authors")
extra_kwargs = { "book_name": { "required": True, "min_length": 2, "error_messages": { "required": "图书名必须提供", "min_length": "图书名不能少于两个字符", } }, "price": {}, }
def validate(self, attrs): print(attrs) return attrs
def validate_book_name(self, obj): print(obj) return obj
|
序列化器与反序列化器整合
fields
需要填写参与序列化与反序列化的字段的并集
在extra_kwargs
中可以通过read_only
与write_only
来指定字段只参与序列化或者只参与反序列化
全局钩子与局部钩子
仍然可以正常使用
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
| class BookModelSerializerV2(serializers.ModelSerializer): class Meta: model = Book fields = ("book_name", "price", "publish", "authors", "pic")
extra_kwargs = { "book_name": { "required": True, "min_length": 2, "error_messages": { "required": "图书名必须提供", "min_length": "图书名不能少于两个字符", } }, "pic": { "read_only": True }, "publish": { "write_only": True }, "authors": { "write_only": True }, }
def validate(self, attrs): print(attrs) return attrs
def validate_book_name(self, obj): print(obj) return obj
|
5. 接口API
更新单个对象整体
修改对象时,在调用序列化器验证数据时必须指定instance
关键字
在调用serializer.save() 底层是通过ModelSerializer
内部的update()
方法来完成的更新
可以在序列化器通过重写update()
方法来完成自定义更新
更新单个对象局部
更新单个局部只需要指定参数partial=True
即可
6. ModelSerializer与Serializer
ModelSerializer
在Serializer
的基础上定制了更多的功能
- 在序列化
ModelSerializer
内部自己实现了create()
方法与update()
方法,在更新以及新增对象时无需自己实现逻辑
- 序列化器数据的校验方式以及字段的自定义方式有所不同
作业
1 2 3 4 5 6 7 8
| 1. 掌握全局钩子与局部钩子的使用方式 ModelSerializer 2. 掌握常见接口的开发 查询单个 查询所有 删除单个 删除所有 新增单个 新增所有 局部修改单个 整个修改单个 3. Django 抽象表的概念
|