Serializer字段与选项大全
常用字段类型
字段 | 字段构造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, |
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(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField(format=‘hex_verbose’) |
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=) |
选项参数
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_lenght | 最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 是否截断空白字符 |
max_value | 最小值 |
min_value | 最大值 |
通用参数
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
required | 表明该字段在反序列化时必须输入,默认True |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器,一个列表 |
error_messages | 包含错误编号与错误信息的字典,一个字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
定义序列化器
方式一:继承serializers.Serializer
- 标准规则
- 和模型类,字段名一样
- 和模型类,字段类型一样
- 和模型类,字段选项一样
- 如果有入库操作,必须是实现create,update方法,内部默认没有实现这两个方法
普通字段
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
period=serializers.IntegerField(default=0)
username=serializers.CharField(max_length=10)
password=serializers.CharField(max_length=16)
选项字段
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
#方式一,获取对应数据库值
period=serializers.IntegerField()
#方式二,显示对应的中文,相当于obj.get_period_display()
pk_name = serializers.CharField(source='get_period_display')
- 注意事项
- 如果与模型字段名不一样,需要使用参数source指定模型字段名
如果有参数source,他会在内部默认执行:obj.period
pk=serializers.CharField(source=‘period’)
- 如果与模型字段名不一样,需要使用参数source指定模型字段名
一对多关系字段
- 从表获取主表
#方式一,设置参数read_only=True 或者 设置queryset=article.objects.all() 返回值只能是id值
article=serializers.PrimaryKeyRelatedField(read_only=True)
article=serializers.PrimaryKeyRelatedField(queryset=article.objects.all())
#方式二,使用模型类__str__方法获取 返回值是 __str__的返回值
article=serializers.StringRelatedField(read_only=True)
#方式三,使用article的序列化器 返回值是序列化器所有的字段
article=ArticleSerializer()
#方式四,使用source指定字段属性值 返回值获取对应一中的单个指定属性值
article_name=serializers.CharField(source='article.name')
#方式五,使用字段函数,格式def get_字段名(self,instance) 返回值获取对应一中的多个指定属性值
article=serializers.SerializerMethodField()
def get_article(self,instance):
article=instance.article
return {'id':article.id,'name':article.name}
- 主表获取从表
#方式一,设置参数read_only=True 或者 设置queryset=article.objects.all() 返回值只能是id值
article_set=serializers.PrimaryKeyRelatedField(read_only=True,many=True)
#方式二,使用模型类__str__方法获取 返回值是 __str__的返回值
article_set=serializers.StringRelatedField(read_only=True,many=True)
#方式三,使用user的序列化器 返回值是序列化器所有的字段
article_set=ArticleSerializer(many=True)
#方式四,使用source指定字段属性值 返回值获取对应多中的单个指定属性值
article_name=serializers.CharField(source='article_set.name')
#方式五,使用字段函数,格式def get_字段名(self,instance) 返回值获取对应多中的多个指定属性值
article=serializers.SerializerMethodField()
def get_article(self,instance):
articles=instance.article_set.all()
ret=[]
for item in articles:
ret.append({'id':item.id,'name':item.name})
return ret
多对多关系字段
主表获取从表的多个属性值
course=serializers.SerializerMethodField()
def get_course(self,row):
objs=row.course_set.all()
ret=[]
for item in objs:
ret.append({'id':item.id,'name':item.name})
return ret
从表获取主表的多个属性值
course=serializers.SerializerMethodField()
def get_course(self,row):
objs=row.course.all()
ret=[]
for item in objs:
ret.append({'id':item.id,'name':item.name})
return ret
一对一关系同理
通过继承serializers.字段类型对字段返回值进行修改
class MyField(serializers.CharField):
def to_representation(self, value):
return 'new'+value
#序列化器中使用的时候,直接username = MyField()
如果有入库,必须实现create 实现update方法
def create(self,validated_data):
#1,创建book对象,设置属性,入库
book=BookInfo.objects.create(**validated_data)
#2,返回
return book
def update(self,instance,validated_data):
#1,更新数据
instande.btitle=validated_data["btitle"]
#2,入库
instance.save()
#或者
instance=instance.upadte(**validated_data)
#3,返回
return instance
方式二:继承serializers.ModelSerializer
- 不用一个一个字段类型的声明了,指定模型之后,会自动根据模型帮助我们声明
- 不用再重写入库方法create,update了,内部已经帮我们实现了
class StudentSerializer(serializers.ModelSerializer):
username = MyField()
# grade=serializers.HyperlinkedIdentityField(view_name='ds',lookup_field='Grade',lookup_url_kwarg='pk')
class Meta:
#需要序列化的模型
model=Student
#需要序列化的字段,“__all__”表示全部字段,列表中的字段也可以混合自定义字段
# fields="__all__"
fields=['username','password','Grade']
#序列化的深度,这是针对一对一,一对多,多对多关系来说的,进行下一个对象的序列化,默认深度为0
depth=0
Meta类其他属性:
- read_only_fields
- 如果希望多个字段是只读状态,可以使用这个快捷方式,一个列表,内部是字段名
- extra_kwargs
- 这是对字段的校验规则,如果在字段声明中已经有了,则会被忽略,这个只是作为额外补充。
- exclude
- 排除某些字段。
在视图中使用序列化器
serializer=UserModelSerializer(
instance="对象(们)",
data="数据(们)",
many=False|True,#与数据或对象配套,代表操作的是否是多个
partial=False|True,#运用在局部修改中,所以校验可以选填(required=False)
context={'request':request}#视图、序列化传参
)
serializer.is_valid(raise_exception=False|True)#校验数据,(raise_exception如果为true,会抛出异常),结果返回布尔类型
serializer.save() #入库操作,执行create或update方法
serializer.data #序列化后的数据
serializer.errors #校验失败的信息
- 总结
- 如果是序列化单个对象,只需要传递参数instance
- 如果是序列化多个对象,不仅传递参数instance,还要传递many=true
- 如果是反序列化创建一个对象,传递参数data ,最后serializer.save()入库
- 如果是反序列化更新一个对象,传递参数instance,还有data,最后serializer.save()入库
- 如果仅仅是想对数据进行校验,传递参数data
对字段进行自定义校验
1. 验证单个字段(validate_验证字段名)
说明:其实model层已经帮我们验证了一些字段,但是不能验证全,比如说 phone手机号,是11位,而且是以 13、15、等开头的规则,那咋办。这个时候我们就要用到 单个字段的验证(phone规则验证)。用法如下:
from rest_framework import serializers
from .models import User
import re
class UserSerializer(serializers.ModelSerializer):
#因为phone没有办法支持11位,需重新定义phone规则。
phone = serializers.CharField(max_length=11,min_length=11,required=True)
class Meta:
model = User
fields = "__all__"
#自定义单个字段验证规则:validate_验证字段名(phone),参数:传入的是当前字段(phone)
#当我们序列化的时候,phone字段就会走自定义序列化函数
def validate_phone(self, phone):
#检测手机是否合法
if not re.match(r'1[3456789]\d{9}',phone):
raise serializers.ValidationError("手机号码不合法") #如果不匹配我抛出一个异常
#检测手机号是否存在
if User.objects.filter(phone=phone).all():
raise serializers.ValidationError("手机号已被注册")
return phone #一定要有返回值,意思就是把你验证后的字段返回给模型类
2. 组合字段验证(validate)
说明:我们有的时候需要验证两个字段,比如说,在注册的时候,需要输入密码,和输入确认密码,但是我们只需要保存一次即可,那这种情况咋办呐。这个时候我们就需要用到validate这种组合验证方式。
from rest_framework import serializers
from .models import User
import re
class UserSerializer(serializers.ModelSerializer):
phone = serializers.CharField(max_length=11,min_length=11,required=True)
#序列化一个新字段pwd1,只是我们这个字段的值不保存数据库,后续验证完毕之后需要删除
pwd1 = serializers.CharField(max_length=64,write_only=True) #write_only表示必须要从前端传递过来
class Meta:
model = User
fields = "__all__"
def validate_phone(self, phone): #单个验证
....
def validate(self, attrs): #组合验证
#print(attrs) #attrs是:OrderedDict([('phone', '13641929925'), ('pwd1', '1234'), ('name', 'gaogao'), ('gender', 1), ('pwd', '1234')])
if attrs.get('pwd1') != attrs.get('pwd'):
raise serializers.ValidationError("两次密码不一样")
attrs.pop('pwd1') #验证完毕需要删除pwd1,因为pwd1在模型类User中没有这个字段
return attrs #一定要有返回值
重写入库方法
-
如果是继承serializers.Serializer的序列化器,有入库操作,必须实现入库方法。
-
如果是继承serializers.ModelSerializer的序列化器,可以根据需要重写入库方法。
1. create
说明:我们在注册密码的时候,需要进行用户密码的加密再存放进数据库,这个时候就需要重写 create 方法。
from rest_framework import serializers
from .models import User
import re
class UserSerializer(serializers.ModelSerializer):
....
class Meta:
model = User
fields = "__all__"
def create(self, validated_data):
#重写create方法,对密码加密完之后,再插入到数据库中
---
user=User.objects.create(**validated_data)
return user
2. update
def update(self, instance, validated_data):
重写方法
return super(TruckSerializer, self).update(instance, validated_data)
choices 单选字段序列化
说明:我们在model类中,有的时候会存choice这样的选项。如下:
from django.db import models
# Create your models here.
class User(models.Model):
genders = ((1, '男'), (2, "女"))
gender = models.IntegerField(choices=genders, verbose_name='性别')
...
很明显 只显示 1或者 2这样的数据,不是我们想要的,那我们咋办呐?两种办法:
方式一,序列化中重新定义gender字段
说明:根据source来源来定义字段,这种方式只能支持序列化,但是不支持反序列化,所以只能获取数据,但是不能创建数据。
from rest_framework import serializers
from .models import User
import re
class UserSerializer(serializers.ModelSerializer):
gender = serializers.CharField(source='get_gender_display') #根据source数据来源定义字段
class Meta:
model = User
fields = "__all__"
方式二,重写 to_representation 方法
说明:前面我们也讲了,所有字段的显示,其实就是在 to_representation方法里面,那我们在 to_representation 方法重新定义 gender字段不就可以了。这样既支持序列化,也可以支持反序列化。
from rest_framework import serializers
from .models import User
import re
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
#重写to_representation方法
def to_representation(self, instance):
representation = super(UserSerializer, self).to_representation(instance) #继承UserSerializer父类
representation['gender'] = instance.get_gender_display() #重新定义gender字段
return representation
额外字段(解决出参时不显示密码字段)
说明:我们在入参的时候可能想输入一些参数,但是在出参的时候,不想显示一些参数,比如说,密码,不可能我注册的时候,响应给我密码多少。那这个怎么解决呐?我们就用额外字段解决。
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
extra_kwargs = { #额外字段:改变我们字段的修饰
"pwd": {"write_only": True} #write_only: True 表示只允许入参,不允许出参
}
Validators验证器
UniqueValidator:对象是唯一
说明:其实这个我们在model模型类中用unique=True 也可以验证。
username = serializers.CharField(
required=True, allow_blank=False, label="用户名",max_length=16,min_length=6,
validators=[UniqueValidator(queryset=User.objects.all(),message="用户已经存在")],
error_messages={
"blank": "用户名不允许为空",
"required": "请输入用户名",
"max_length": "用户名长度最长为16位",
"min_length": "用户名长度至少为6位"
})
UniqueTogetherValidator:联合唯一
说明:两个组合联合唯一
class UserFav(models.Model):
user = models.ForeignKey(User,verbose_name="用户",on_delete=False)
goods = models.ForeignKey(Goods,verbose_name="商品",on_delete=False)
add_time = models.DateTimeField(default=datetime.now,verbose_name="用户收藏")
class Meta:
verbose_name = "用户收藏"
verbose_name_plural=verbose_name
unique_together = (('user','goods'),)
class UserFavSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = UserFav
fields = ('id','user', 'goods')
validators = [UniqueTogetherValidator(queryset=UserFav.objects.all(),fields=('user','goods'),message='您已收藏')]
自定义Validators验证器
#校验类
class PasswordValidator(object):
def __call__(self, value):
if len(value)<=6:
message = '密码太短'
raise serializers.ValidationError(message)
def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 执行验证之前调用,serializer_fields是当前字段对象
pass