drf 序列化器分析使用

1、序列化器的使用

1、序列化:格式转换--把python中的对象转换成json格式字符串
2、反序列化:反转--json格式的字符串转成python格式的对象
3、drf序列化组件(序列化器)
	Response可以转换很多、用Response不用JsonResponse了
1.1 models表
class Staff(models.Model):
    name = models.CharField(max_length=64,verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    department = models.ForeignKey(to='Department',on_delete=models.CASCADE,
                                   verbose_name='部门')
    projects = models.ManyToManyField(to='Project')

    class Meta:
        verbose_name_plural = '员工表'

    def __str__(self):
        return self.name

class Department(models.Model):
    name = models.CharField(max_length=64,verbose_name='部门名称')
    contact = models.IntegerField(verbose_name='部门电话')
    email = models.IntegerField(verbose_name='部门邮箱')
    class Meta:
        verbose_name_plural = '部门表'

    def __str__(self):
        return self.name

class Project(models.Model):
    name = models.CharField(max_length=128,verbose_name='项目名称')
    price = models.IntegerField(verbose_name='启动资金',default=0)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural='项目表'

####1.2 建serializer.py书写类

settings-----app注册
INSTALLED_APPS = [
    'rest_framework'
]


1、写一个序列化的类继承 Serializer
2 在类中写要序列化的字段
3 在视图类中使用(实例化)
4 得到序列化后的数据,返回
5 字段参数,source,指定要序列化表中的哪个字段

from rest_framework import serializers
class StaffSerializer(serializers.Serializer):
    # 在这里写要序列化的字段
    # 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
    # 字段类,有很多字段参数()
    name = serializers.CharField()
    age = serializers.IntegerField()
    
    department = serializers.CharField()  #拿到对象、"Department object (1)
        models中字段下书写---就会拿到 department的name
        def __str__(self)
             return self.name   
        
'source指定字段参数 指定要序列化的字段 ' source不能和赋值变量名冲突
     department = serializers.CharField(source='department.email')
    
'   跨表查使用较多'   (要么是列表,要么是字典)
	department = serializers.SerializerMethodField()
    def get_department(self, obj):
        return {'name':obj.department.name,'city':obj.department.contact}

1.3 views
from rest_framework.response import Responsefrom app01 
import modelsfrom rest_framework.views 
import APIViewfrom app01.serializer 
import StaffSerializer​
#查所有path('text/',views.StaffView.as_view()),
class StaffView(APIView):    
	def get(self, request):        
        staff_list = models.Staff.objects.all()        
        # instance=None, 要序列化的数据        
        # data=empty  ,要反序列化的数据(目前data先不用)        
        # many=True 如果序列化多条,一定要写many=True        
        staff_ser = StaffSerializer(instance=staff_list, many=True)        
        # book_ser.data就是序列化后的数据        
        return Response(staff_ser.data)    #查单个path('text/<int:id>/',views.StaffViewId.as_view()),
    class StaffViewId(APIView):    def get(self,request,id):        
            staff = models.Staff.objects.all().filter(pk=id).first()        
            staff_ser = StaffSerializer(instance=staff)       
return Response(staff_ser.data)
1.4 模型表中写方法

# 表模型中写的
def publish_name(self):
   return {'name':self.publish.name,'city':self.publish.city}

@property
def author_list(self):
   return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]

#序列化类中
# publish = serializers.CharField(source='publish_name')
publish_name = serializers.DictField()
author_list=serializers.ListField()

2、反序列化、钩子

2.1 serializer视图
*继承Serializer类  必须重写create、update方法
class StaffSerializer(serializers.Serializer):
    name = serializers.CharField()
    age = serializers.IntegerField()
    # department = serializers.CharField()  #拿到对象、"Department object (1)
    #     def __str__(self)
    #         return self.name   #拿到 department的name
    department = serializers.CharField(source='department.name')
   #拿到字典、
    # department = serializers.SerializerMethodField()
    # def get_department(self, obj):
    #     return {'name':obj.department.name,'city':obj.department.contact}

    def create(self, validated_data):
        #需要取到外键字段id、添加外键字段
        department_id = validated_data.get('department').get('name')
        del validated_data['department']
        return models.Staff.objects.create(department_id=department_id,
                                           **validated_data)
    #局部钩子校验
    def validate_name(self,data):
        #data当前字段的值
        if data.startswith('sb'):
            raise ValidationError('不能以<sb>开头')
        else:
            return data
    #全局钩子
    def validate(self,attrs):
        if attrs.get('name') == attrs.get('age'):
            raise ValidationError('名字和年龄不能一样')
        else:
            return attrs
2.2增加数据需要进行反序列化、并且对数据进行校验’–views视图
员工表--外键department--多对多peoject
class StaffView(APIView):
    def post(self, request):   是drf的request
        data = request.data     **取到数据
        staff_ser = StaffSerializer(data=data)   *对数据进行序列化成json格式的字符串
        if staff_ser.is_valid(raise_exception=True):  *对数据进行校验
            #可以在API中全局复写校验错误响应的格式
            staff_ser.save()                     *校验通过保存
            return Response(staff_ser.data)		*返回结果
        else:
            return Response(staff_ser.errors)	*错误信息、返回应该还带着状态码
2.3序列化类 常用和非常用字段
参考博客--
	http://www.liuqingzheng.top/python/Django-rest-framework%E6%A1%86%E6%9E%B6/2-drf-%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6/
2.4 字段参数
# 针对charfield
max_length	最大长度
min_lenght	最小长度
allow_blank	是否允许为空
# 针对interfield
max_value	最小值
min_value	最大值

# 通用的,大家都有
#这两个最重要
read_only	表明该字段仅用于序列化输出,默认False(序列化)
write_only	表明该字段仅用于反序列化输入,默认False(反序列化)


required	表明该字段在反序列化时必须输入,默认True
default	反序列化时使用的默认值
allow_null	表明该字段是否允许传入None,默认False
error_messages	包含错误编号与错误信息的字典

validators	该字段使用的验证器(了解) 

3、模型序列化器–重要

序列化类 --ModelSerializer模型序列化器
-ModelSerializer是对Serializers进一步的封装、
继承了ModelSerializer无需重写create、update方法
'from rest_framework.serializers import ModelSerializer'

class DepartmentSerializer(serializers.Serializer):
    nid = serializers.IntegerField(required=False)
    name= serializers.CharField(max_length=3, error_messages={'max_length': '太长了小伙子'})
    contact = serializers.IntegerField(read_only=True)
    email = serializers.EmailField(write_only=True)

class StaffModelSerializer(ModelSerializer):
    class Meta:
        model = models.Staff
        #1、取全部字段
        fields = '__all__'
        #2、自定义包含字段
        fields = ['name','age']
        #3、排除某个字段
        exclude=['name',]   23只能用一个、3一般不用
        extra_kwargs = {
            	#write_only:True和read_only:True不能同时用
            'department':{'required':True,'write_only':True},
            'project':{'required':True,'write_only':True},
        }
    department_detail =  DepartmentSerializer(source='department',read_only=True)
    project_list = serializers.ListField(read_only=True)
views

class StaffView(APIView):
    #查所有
    def get(self, request):
        staff_list = models.Staff.objects.all()

        staff_ser = StaffModelSerializer(instance=staff_list, many=True)
        # book_ser.data就是序列化后的数据
        return Response(staff_ser.data)
	#增加
    def post(self, request):
        data = request.data
        staff_ser = StaffModelSerializer(data=data)
        if staff_ser.is_valid(raise_exception=True):
            staff_ser.save()
            return Response(staff_ser.data)
        else:
            return Response(staff_ser.errors)
        

class StaffViewId(APIView):
    # 查单个
    def get(self, request, id):
        staff = models.Staff.objects.all().filter(pk=id).first()
        staff_ser = StaffModelSerializer(instance=staff)
        return Response(staff_ser.data)
	#改单个
    def put(self, request, id):
        staff = models.Staff.objects.filter(pk=id).first()
        staff_ser = serializer.StaffModelSerializer(instance=staff, data=request.data)
        if staff_ser.is_valid():
            staff_ser.save()
            return Response(staff_ser.data)
        else:
            return Response(staff_ser)
	#删单个
    def delete(self, request, id):
        res = models.Staff.objects.filter(pk=id).delete()
        if res[0] > 0:   res--影响行数 res--元组、需要取出[0]
            return Response('')
        else:
            return Response('要删的不存在')

models
from django.db import models
class Staff(models.Model):

    name = models.CharField(max_length=64,verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    department = models.ForeignKey(to='Department',on_delete=models.CASCADE,
                                   verbose_name='部门')
    projects = models.ManyToManyField(to='Project')

    class Meta:
        verbose_name_plural = '员工表'

    def __str__(self):
        return self.name

    def department_name(self):
        return {'name':self.department.name,'contact':self.department.contact}

    @property
    def project_list(self):
        return [{'name':project.name,'price':project.price} for project in self.projects.all()]

路由
path('books/',views.StaffView.as_view()),
path('books/<int:id>/',views.StaffViewIda.as_view()),
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值