02 Django REST Framework 序列化

 01-创建序列化类

# 方式一:
publish_list = models.Publish.objects.all()
# 导入序列化组件
from django.core import serializers

serializers.serialize("json", publish_list)

 

# 方式二:
# 为queryset和model对象做序列化


class PublishSerializers(serializers.Serializer):
    # 添加做序列化的字段
    name = serializers.CharField()
    email = serializers.CharField()

publish_list = models.Publish.objects.all()

PublishSerializers(publish_list, many=True)

PublishSerializers(model_obj)

 Response

from rest_framework.response import Response
# 序列化 一对多  多对多

class BookSerializers(serializers.Serializer):
    # 添加做序列化的字段
    title = serializers.CharField()
    price = serializers.CharField()
    # 一对多
    publish = serializers.CharField(source="publish.name")
    
    # 多对多
    authors = serializers.SerializerMethodField()
    
    def get_authors(self, obj):
        temp = []
        for obj in obj.authors.all():
            temp.append(obj.name)

02-ModelSerializer

# 等同于上面的

from rest_framework.views import APIView

class BookModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = Book  # 表名
        fields = "__all__"


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        bs = BookModelSerializers(book_list, many=True)

        return Response(bs.data)

    def post(self):
        pass

03-提交post请求

class BookView(APIView):
    def get(self, request):
        '''
        获取书籍
        :param request:
        :return:
        '''
        book_list = Book.objects.all()
        bs = BookModelSerializers(book_list, many=True)

        return Response(bs.data)

    def post(self, request):
        '''
        添加书籍
        :return:
        '''
        # post请求的数据
        bs = BookModelSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 调用的是create方法
            # 返回的是添加的数据
            return Response(bs.data)
        else:
            # 错误的数据
            return HttpResponse(bs.errors)

04-重写save中create方法

class BookModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = Book  # 表名
        fields = "__all__"

    publish = serializers.CharField(source="publish.pk)
    # 针对一对多字段publish,会报错,所以重写create方法
    def create(self, validated_data):
        book = Book.objects.create(title=validated_data["title"], price = validated_data["price"], pub_date = validated_data["pub_date"])
        book.authors.add(*validated_data["authors"])

        return book

 05-自定义方法

class UserInfoSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source="get_user_type_display")
    group = serializers.CharField(source="group.title")
    rls = serializers.SerializerMethodField()

    def get_rls(self, row):
        # 获取用户所有的角色
        role_obj_list = row.roles.all()
        ret = []
        # 获取角色的id和名字
        # 以字典的键值对方式显示
        for item in role_obj_list:
            ret.append({"id": item.id, "title": item.title})
        return ret

    class Meta:
        model = models.UserInfo
        fields = ['id','username','password','type','group','rls']

06-自动序列化连表(depth)

class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        #fields = "__all__"
        fields = ['id','username','password','group','roles']
        #表示连表的深度
        depth = 1

07-生成url

# urls.py

urlpatterns = [
    re_path('(?P<version>[v1|v2]+)/group/(?P<pk>\d+)/', GroupView.as_view(),name = 'gp')    #序列化生成url
]

 

class UserInfoSerializer(serializers.ModelSerializer):
    # 获取url
    group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='pk')
    class Meta:
        model = models.UserInfo
        #fields = "__all__"
        fields = ['id','username','password','group','roles']
        #表示连表的深度
        depth = 0

效果:

 08-自定义数据验证规则

# 自定义验证规则
class GroupValidation(object):
    def __init__(self,base):
        self.base = base

    def __call__(self, value):
        if not value.startswith(self.base):
            message = "标题必须以%s为开头"%self.base
            raise serializers.ValidationError(message)


class UserGroupSerializer(serializers.Serializer):
    title = serializers.CharField(validators=[GroupValidation('以我开头'),])    

class UserGroupView(APIView):
    def post(self,request,*args, **kwargs):
        ser = UserGroupSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data['title'])
        else:
            print(ser.errors)

        return HttpResponse("用户提交数据验证")

 09-序列化外键用嵌套的方法来实现

示例:

# 轮播图
class GoodsImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsImage
        fields = ("image",)

# 商品列表页
class GoodsSerializer(serializers.ModelSerializer):
    # 覆盖外键字段
    category = CategorySerializer()
    # images是数据库中设置的related_name="images",把轮播图嵌套进来
    images = GoodsImageSerializer(many=True)
    class Meta:
        model = Goods
        fields = '__all__'

 10-添加自定义字段 不在model字段内

class ForgetPWDSerializers(serializers.ModelSerializer):
    re_password = serializers.CharField(write_only=True)

    class Meta:
        model = UserModel
        fields = ('username', 'password', 're_password')

原理:create最后在返回response体的时候,传递的参数serializer.data,其实做的是一个序列化的工作,它会依据你在class Meta里面设置的fields,去做序列化,将里面所有字段进行序列化,这个时候就会报错!

解决方法:write_only 设置这个属性为true,去确保create/update的时候这个字段被用到,序列化的时候,不被用到!

 11-

 12-获取choice的值

# 指定 source="get_category_display"

CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True)

13-设定不需要校验字段

# required=False

id = serializers.IntegerField(required=False)

14-序列化字段与反序列化字段

# 前端 传 w_category 字段,序列化用category,反序列化用 w_category

category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True)
w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
read_only=True 序列化字段;
write_only=True 反序列化字段;
book_obj = {
        "title": "Alex的使用教程",
        "w_category": 1,
        "pub_time": "2018-10-09",
        "publisher_id": 1,
        "author_list": [1, 2]
    }


class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32, validators=[my_validate])
    CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
    category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True)
    w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
    pub_time = serializers.DateField()

    publisher = PublisherSerializer(read_only=True)
    publisher_id = serializers.IntegerField(write_only=True)
    author = AuthorSerializer(many=True, read_only=True)
    author_list = serializers.ListField(write_only=True)

    def create(self, validated_data):
        book = Book.objects.create(title=validated_data["title"], category=validated_data["w_category"],
                                pub_time=validated_data["pub_time"], publisher_id=validated_data["publisher_id"])
        book.author.add(*validated_data["author_list"])
        return book

    def update(self, instance, validated_data):
        instance.title = validated_data.get("title", instance.title)
        instance.category = validated_data.get("category", instance.category)
        instance.pub_time = validated_data.get("pub_time", instance.pub_time)
        instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
        if validated_data.get("author_list"):
            instance.author.set(validated_data["author_list"])
        instance.save()
        return instance

    def validate_title(self, value):
        if "python" not in value.lower():
            raise serializers.ValidationError("标题必须含有python")
        return value

    def validate(self, attrs):
        if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
            return attrs
        else:
            raise serializers.ValidationError("分类以及标题不符合要求")
第一版
class BookSerializer(serializers.ModelSerializer):
    category_display = serializers.SerializerMethodField(read_only=True)
    publisher_info = serializers.SerializerMethodField(read_only=True)
    authors = serializers.SerializerMethodField(read_only=True)

    def get_category_display(self, obj):
        return obj.get_category_display()

    def get_authors(self, obj):
        authors_query_set = obj.author.all()
        return [{"id": author_obj.id, "name": author_obj.name} for author_obj in authors_query_set]

    def get_publisher_info(self, obj):
        # obj 是我们序列化的每个Book对象
        publisher_obj = obj.publisher
        return {"id": publisher_obj.id, "title": publisher_obj.title}

    class Meta:
        model = Book
        # fields = ["id", "title", "pub_time"]
        fields = "__all__"
        # depth = 1
        extra_kwargs = {"category": {"write_only": True}, "publisher": {"write_only": True},
                        "author": {"write_only": True}}
第二版ModelSerializer

 

15-put允许部分更新字段:partial=True

16-自定义校验方法 my_validate

# 三种 校验数据的方式:
1. 校验全部字段  
    validate

2. 校验单个字段 如:title
    validate_title

3. 自定义校验方法  
    my_validate

def my_validate(value):
    if "敏感信息" in value.lower():
        raise serializers.ValidationError("不能含有敏感信息")
    else:
        return value

  my_validate的权重 高于 validate_title

17-设置depth = 1,获取外键字段及多对多字段的值

class BookSerializer(serializers.ModelSerializer):
    # 获取 category 字段的选择 的值,是数字对应的值,而不是数字
    category = serializers.CharField(source="get_category_display")

    class Meta:
        model = Book
        # fields = ["id", "title", "pub_time"]
        fields = "__all__"
        depth = 1

18-SerializerMethodField 用于 外键字段 等,只获取想要的字段的值

class BookSerializer(serializers.ModelSerializer): 
    category_display = serializers.SerializerMethodField(read_only=True)
    publisher_info = serializers.SerializerMethodField(read_only=True)
    authors = serializers.SerializerMethodField(read_only=True)

    def get_category_display(self, obj):
        return obj.get_category_display()

    def get_authors(self, obj):
        authors_query_set = obj.author.all()
        return [{"id": author_obj.id, "name": author_obj.name} for author_obj in authors_query_set]

    def get_publisher_info(self, obj):
        # obj 是我们序列化的每个Book对象
        publisher_obj = obj.publisher
        return {"id": publisher_obj.id, "title": publisher_obj.title}

    class Meta:
        model = Book
        # fields = ["id", "title", "pub_time"]
        fields = "__all__"
        # depth = 1
        extra_kwargs = {"category": {"write_only": True}, "publisher": {"write_only": True},
                        "author": {"write_only": True}}

 

 

转载于:https://www.cnblogs.com/pgxpython/p/9961944.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值