模型类序列化器ModelSerializer
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:
- 基于模型类自动生成一系列字段
- 基于模型类自动为Serializer生成validators,比如unique_together
- 包含默认的create()和update()的实现
1. 定义
比如我们创建一个BookInfoSerializer:
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo # 指定生成字段的模型类
fields = '__all__' # 表示包含所有的字段
- model 指明参照哪个模型类
- fields 指明为模型类的哪些字段生成
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
2. 指定字段
1) 使用fields来明确字段,__all__
表示包含所有字段,也可以写明具体哪些字段,如
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo # 指定生成字段的模型类
# fields = '__all__' # 表示包含所有的字段
fields = ('btitle', 'bread') # 指定模型类中的字段
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
btitle = CharField(label='名称', max_length=20)
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
2) 使用exclude可以明确排除掉哪些字段
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo # 指定生成字段的模型类
# fields = '__all__' # 表示包含所有的字段
# fields = ('btitle', 'bread') # 指定模型类中的字段
# exclude 表示排除掉哪些字段
exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
BookModelSerializer():
id = IntegerField(label='ID', read_only=True)
bpub_date = DateField(label='发布日期')
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_delete = BooleanField(label='逻辑删除', required=False)
从上面的显示结果,我们发现已经没有btitle这个字段信息了,已经排除掉了
修改增加选项参数的使用
通过上面的显示结果,我们发现
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
这个不是我们想要的结果,如何修改相关的参数呢?
3) 显示指明字段,如下面代码:
class BookModelSerializer(serializers.ModelSerializer):
# 显示指明字段
bread = serializers.IntegerField(max_value=100, min_value=20)
class Meta:
model = BookInfo # 指定生成字段的模型类
fields = '__all__' # 表示包含所有的字段
# fields = ('btitle', 'bread') # 指定模型类中的字段
# exclude 表示排除掉哪些字段
# exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
BookModelSerializer():
id = IntegerField(label='ID', read_only=True)
bread = IntegerField(max_value=100, min_value=20)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
通过显示指明字段的方式成功的修改了字段的信息
bread = IntegerField(max_value=100, min_value=20)
添加额外参数
我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
class BookModelSerializer(serializers.ModelSerializer):
# 显示指明字段
bread = serializers.IntegerField(max_value=100, min_value=20)
class Meta:
model = BookInfo # 指定生成字段的模型类
fields = '__all__' # 表示包含所有的字段
# fields = ('btitle', 'bread') # 指定模型类中的字段
# exclude 表示排除掉哪些字段
# exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
# 添加修改字段选项参数
extra_kwargs={
"bcomment":{
'max_value':100
},
'btitle':{
'min_length':5
}
}
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
id = IntegerField(label='ID', read_only=True)
bread = IntegerField(max_value=100, min_value=20)
btitle = CharField(label='名称', max_length=20, min_length=5)
bpub_date = DateField(label='发布日期')
bcomment = IntegerField(label='评论量', max_value=100, min_value=-2147483648, required=False)
is_delete = BooleanField(label='逻辑删除', required=False)
分析 btitle = models.CharField(max_length=20, verbose_name='名称')
通过 extra_kwargs 修改 当没有 'min_length':5 这个属性时,会增加,当有这个属性时会修改
btitle = CharField(label='名称', max_length=20, min_length=5)
当模型类中没有这个字段时,如何增加这个字段,需要显示指明字段,如下面代码:
class BookModelSerializer(serializers.ModelSerializer):
# 显示指明字段
bread = serializers.IntegerField(max_value=100, min_value=20)
# 模型类没有的字段,增加字段时,需要显示指明字段
sms_code = serializers.CharField(max_length=6, min_length=6)
class Meta:
model = BookInfo # 指定生成字段的模型类
fields = '__all__' # 表示包含所有的字段
# fields = ('btitle', 'bread') # 指定模型类中的字段
# exclude 表示排除掉哪些字段
# exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
# 添加修改字段选项参数
# extra_kwargs={
# "bcomment":{
# 'max_value':100
# },
# 'btitle':{
# 'min_length':5
# }
# }
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
id = IntegerField(label='ID', read_only=True)
bread = IntegerField(max_value=100, min_value=20)
sms_code = CharField(max_length=6, min_length=6)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(label='发布日期')
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
is_delete = BooleanField(label='逻辑删除', required=False)
我们发现上面显示的结果,增加了 sms_code = CharField(max_length=6, min_length=6) 这个字段信息
注意事项:
fields = ('btitle', 'bread') # 指定模型类中的字段
这种精确指定字段,必须包含显示指明字段,否则会报如下错误信息:
AssertionError Traceback (most recent call last)
~\AppData\Local\Programs\Python\Python36\lib\site-packages\IPython\core\formatters.py in __call__(self, obj)
700 type_pprinters=self.type_printers,
701 deferred_pprinters=self.deferred_printers)
--> 702 printer.pretty(obj)
703 printer.flush()
704 return stream.getvalue()
~\AppData\Local\Programs\Python\Python36\lib\site-packages\IPython\lib\pretty.py in pretty(self, obj)
392 if cls is not object \
393 and callable(cls.__dict__.get('__repr__')):
--> 394 return _repr_pprint(obj, self, cycle)
395
396 return _default_pprint(obj, self, cycle)
~\AppData\Local\Programs\Python\Python36\lib\site-packages\IPython\lib\pretty.py in _repr_pprint(obj, p, cycle)
698 """A pprint that just redirects to the normal repr function."""
699 # Find newlines and replace them with p.break_()
--> 700 output = repr(obj)
701 lines = output.splitlines()
702 with p.group():
~\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py in __repr__(self)
521
522 def __repr__(self):
--> 523 return representation.serializer_repr(self, indent=1)
524
525 # The following are used for accessing `BoundField` instances on the
~\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\utils\representation.py in serializer_repr(serializer, indent, forc
e_many)
75 fields = force_many.fields
76 else:
---> 77 fields = serializer.fields
78
79 for field_name, field in fields.items():
~\AppData\Local\Programs\Python\Python36\lib\site-packages\django\utils\functional.py in __get__(self, instance, cls)
46 if instance is None:
47 return self
---> 48 res = instance.__dict__[self.name] = self.func(instance)
49 return res
50
~\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py in fields(self)
347 # even if Django's app-loading stage has not yet run.
348 fields = BindingDict(self)
--> 349 for key, value in self.get_fields().items():
350 fields[key] = value
351 return fields
~\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py in get_fields(self)
1027 # Retrieve metadata about fields & relationships on the model class.
1028 info = model_meta.get_field_info(model)
-> 1029 field_names = self.get_field_names(declared_fields, info)
1030
1031 # Determine any extra field arguments and hidden fields that
~\AppData\Local\Programs\Python\Python36\lib\site-packages\rest_framework\serializers.py in get_field_names(self, declared_fields, info)
1128 "'fields' option.".format(
1129 field_name=field_name,
-> 1130 serializer_class=self.__class__.__name__
1131 )
1132 )
AssertionError: The field 'sms_code' was declared on serializer BookModelSerializer, but has not been included in the 'fields' option.
精确指定字段,必须包含显示指明字段,正确代码如下:
class BookModelSerializer(serializers.ModelSerializer):
# 显示指明字段
btitle = serializers.IntegerField(max_value=100, min_value=20)
# 模型类没有的字段,增加字段时,需要显示指明字段
sms_code = serializers.CharField(max_length=6, min_length=6)
class Meta:
model = BookInfo # 指定生成字段的模型类
# fields = '__all__' # 表示包含所有的字段
fields = ('btitle', 'bread', 'sms_code') # 精确指定的字段
# exclude 表示排除掉哪些字段
# exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
# 添加修改字段选项参数
# extra_kwargs={
# "bcomment":{
# 'max_value':100
# },
# 'btitle':{
# 'min_length':5
# }
# }
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
btitle = IntegerField(max_value=100, min_value=20)
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
sms_code = CharField(max_length=6, min_length=6)
4) 指明只读字段
可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
class BookModelSerializer(serializers.ModelSerializer):
# 显示指明字段
btitle = serializers.IntegerField(max_value=100, min_value=20)
# 模型类没有的字段,增加字段时,需要显示指明字段
sms_code = serializers.CharField(max_length=6, min_length=6)
class Meta:
model = BookInfo # 指定生成字段的模型类
# fields = '__all__' # 表示包含所有的字段
fields = ('btitle', 'bread', 'sms_code') # 精确指定的字段
read_only_fields = ('bread',) # 指明只读字段
# exclude 表示排除掉哪些字段
# exclude = ('btitle',) # 元组只有一个的时候,注意后面需要加一个逗号(,)
# 添加修改字段选项参数
# extra_kwargs={
# "bcomment":{
# 'max_value':100
# },
# 'btitle':{
# 'min_length':5
# }
# }
我们可以在python manage.py shell中查看自动生成的BookModelSerializer的具体实现
>>> from book_drf.serializer import BookModelSerializer
>>> BookModelSerializer()
BookModelSerializer():
btitle = IntegerField(max_value=100, min_value=20)
bread = IntegerField(label='阅读量', read_only=True)
sms_code = CharField(max_length=6, min_length=6)