序列化器Serializer与ModelSerializer以及在使用中的技巧
一:Serializer使用中的一些理解
1)对于增加数据需要实现create方法,对于修改数据需要实现update方法
.
2)所有要经过序列化的字段必须要写出,并指定是否只序列化read_only或只做反序列化write_only指定为True,对于不需要必传的字段指定required=False.
.
3)通过实现 validate_字段名(self, value)进行字段验证,通过def validate(self, attrs):进行组合验证,所有数据都在attrs中,验证完要进行返回return attrs。验证会在视图层调用serializer.is_valid(raise_exception=True)时触发。
二:ModelSerializer使用中的一些理解
1)需要一个元类 class Meta: 中去配置要序列化哪些字段,以及对这些字段的一些限制
.
2)如:
model指定数据库模型,
fields指定映射哪些字段,
exclide指定的字段为:(除了这些字段其他的都映射),
read_only_fields指定的为只做序列化的,
对于特定的字段进行约束可以通过extra_kwargs
例如:
extra_kwargs= { # 修改参数选项
‘UPassword’: {‘write_only’:True},
}
等等,就写这些,有问题再csdn
三: 对于序列化关系,自己解决过的一些问题
-
)通过 serializers.RelatedField 实现 输出主表的数据时,**指定一个字段输出 (外键是这个主表的表的字段,这里序列化器可以是继承ModelSerializer,也可以是继承Serializer。ModelSerializer与Serializer也是serializers.ModelSerializer与serializers.Serializer。
a) 首先我们要看models模型的代码(特别注意一下外键的参数设置)如下:
这里特别要注意 我们指定的的 related_name=‘一个名字’,这里指定的
名字,在主表进行序列化输出是,可以增加一个相同名字的字段进行其对应
外键所在表的字段输出# 一个主表用户表 class Users(models.Model): ‘’‘各种字段’‘’ ... class Meta: ... # 一个带外键的表,追 class Equip(models.Model): ... # 这里特别要注意 我们指定的的 related_name='一个名字',这里指定的 # 名字,在主表进行序列化输出是,可以增加一个相同名字的字段进行其对应 # 外键所在表的字段输出 Euid = models.ForeignKey(Users,related_name='Equips', on_delete=models.CASCADE) ... class Meta: ...
b) 我们再看序列化器的代码:
指定一个序列化外键所在表字段的类
我们需要一个继承serializers.RelatedField的类,然后实现 to_representation方法,在这个方法里返回我们所需要的外键所在表的字段,value参数就代表了外键表中的一个模型
# 用户装备序列化 一对多数据输出 class EquipsField(serializers.RelatedField): def to_representation(self, value): return '%s' % value.EName
主键的表进行序列化输出时,带上外键所在表的某个字段:
重点我们看这里,EquipsField是我们自定一个序列化器类,
Equips 是我们在models模型时就限定的一个字段名字,
这样我们就可以通过这个字段找到对应 外键所在的表了class UserRegSerializer(serializers.Serializer): ... # 重点我们看这里,EquipsField是我们自定一个序列化器类, #Equips 是我们在models模型时就限定的一个字段名字, #这样我们就可以通过这个字段找到对应 外键所在的表了 Equips = EquipsField(many=True, read_only=True) ...
-
数据库中不存在的坐标,临时的进行序列化输出 serializers.SerializerMethodField
通过serializers.SerializerMethodField 实现临时的字段,需要赋值的字段名下面会用
这个字段的值需要实现 def get_字段名(self,obj) 这里的obj 就是当前的模型对象代码:
class UserLoginSerializer(serializers.ModelSerializer): ... # 通过serializers.SerializerMethodField 实现临时的字段,需要赋值的字段名下面会用 # 这个字段的值需要实现 def get_字段名(self,obj) 这里的obj 就是当前的模型对象 token = serializers.SerializerMethodField(label='token', read_only=True) ... class Mate: ... def get_token(self, obj): jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(obj) token = jwt_encode_handler(payload) return token
-
像serializers.RelatedField所创建的类只可以做主键表序列化输出时使用,当要通过主表进行反序列化的时候,向外键所在的表添加数据可以通过 一个字段实现外键所在序列化类的对象的形式去搞定
外键需要一个序列化器,在主键表的序列化器中有一个字段实现了外键的序列化器对象,实现create方法在,主键表的模型对象中提取出外键的数据,通过外键的模型调用create方法进行保存外键的数据!!!!!就是这样!!!!yes
代码:
# 外键所在表的 序列化器 class PhotoGallerySerializer(serializers.Serializer): # Gid 是本表的一个外键,对应的主键表为 Group Gid = serializers.PrimaryKeyRelatedField(queryset=Group.objects.all(),error_messages={"error":"无此任务"}) images = serializers.ImageField(label='人脸图片') Url = serializers.CharField(max_length=100, label='人脸图片链接', required=False) def create(self, validated_data): image = PhotoGallery.objects.create(**validated_data) urlFormat(image, image.images) return image # 主键所在表的序列化器 class GroupSerializer(serializers.ModelSerializer): ... # 我们通过外键序列化器 实现一个字段,因为我们是ModelSerializer # 虽然已经集成了create方法,但是,由于我们要向外键表存数据,要重写create函数 # 而外键的数据也是在主键表这里反序列化时带的,所以肯定要走create函数 # 所以我们对应 Urls这个外键表的数据进行存储时,要在Group的create函数里实现,如下面 Urls = PhotoGallerySerializer(many=True, required=False) # 由于我们要传图片, 所以需要一个存储图片路径的字段,后期通过 # 取出这个字段拼接绝对路径,进行传输七牛云生成外链图 GImage = serializers.ImageField(label='人脸图片') def create(self, validated_data): # Group模型的数据 group = Group.objects.create(**validated_data) # 我们需要其中的图片路径,因为外键表是一个图片库,通过编写的format # 对接七牛云返回外链 urls = urlformat(group.GImage) # 在创建群组的时候,要向其外键的表保存图片 photoValidated_data = { 'images': group.GImage, 'Url': urls, 'Gid_id': group.id } # 通过 create保存外键表的数据 PhotoGallery.objects.create(**photoValidated_data) return group ...
*) 在这里补充一下图片上传,的models代码如下
图片的字段或者文件的字段, 通过 upload_to 指定自己写好的fromat函数,返回的是图片上传后会生成的名字不会出现重复。
刚开始上传的时候,图片还是原名,因为要进行上传服务器的时候,要用到这个模型的参数,所以保存到本地的时候会保存动态生成的文件名,这个evaluation_directory_path_face返回的值就存到了数据库里,但是返回的这个值并不是字符串,而是一个文件型的变量代码:
# 使用uuid创建唯一的图片名,并保存的路径和文件名一并返回 def evaluation_directory_path_face(product_id, filename): ext = filename.split('.')[-1] filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext) return os.path.join("static/face", filename) # 需要上传图片的表 class Group(models.Model): # 图片的字段或者文件的字段, 通过 upload_to 指定自己写好的fromat函数, # 返回的是图片上传后会生成的名字不会出现重复 GImage = models.ImageField(null=True, blank=True, upload_to=evaluation_directory_path_face, verbose_name="人脸识别图像", default='')
四:主从表的一些操作例子
url: https://www.cnblogs.com/xiaogongjin/p/13288397.html 这边有一些别的博主写的博客,可以参考一下
我讲两句!!! 嗯…啊…哈哈哈没啥可说的。就这点b东西!
昨天是曼巴逝世一周年,曼巴精神一直感染着我,像他一样,永不放弃,对于困难,越艰难越要爱上挑战,不断提高自己。 Kobe Bean Bryant 是我永远的榜样。在自己选择的道路上即使自己没有天赋,也要尽自己的努力做好自己所能做到的!加油,曼巴精神永远记在我心!