您现在的位置是:网站首页 > 分类 > 文章详情

drf序列化知识点

T2019年6月12日 14:37334人围观
简介drf序列化常用的知识点

1、参数校验、write_only、read_only
1)model.py

class TestSer(models.Model):
    name = models.CharField(max_length=20)
    age = models.IntegerField()
    love = models.CharField(max_length=50)

2)serializers.py

from rest_framework import serializers
from .models import *
from rest_framework.validators import UniqueTogetherValidator


class TestSerSerializer(serializers.ModelSerializer):
    # 有时候需要返回一个值给前端,但是model中并不存在,就用read_only=True
    test_r = serializers.CharField(max_length=20, read_only=True)
    # 有时候前端需要传入一个值,但是这个值model中并不存在,就用write_only=True的方式,记得重写下validate
    test_w = serializers.CharField(max_length=10, write_only=True)
    name = serializers.CharField(required=True, allow_blank=False, max_length=20, min_length=6,allow_null=False,
                            error_messages={'required': '缺少参数name', "blank": "名称不能为空", 'max_length': '用户名最大长度为20','min_length': '用户名最小长度为6'})  # 校验方式1

    # 重写serializers里面的validate方法,返回的attrs必须是model中存在的字段,不然post请求instance.save()时会报错,因此我们可以在validate方法中del attrs['test_w']解决此问题
    def validate(self, attrs):
        print(attrs)
        del attrs['test_w']
        # 校验方式3,默认返回给前端错误信息的key是non_field_errors,可再settings中配置'NON_FIELD_ERRORS_KEY': 'error'即可
        if not attrs['name'].startswith('王者'):
            raise serializers.ValidationError('名称必须以 王者 开头',code='starwith')
        return attrs

    class Meta:
        model = TestSer
        fields = "__all__"
        # 校验方式2
        validators = [
            UniqueTogetherValidator(
                queryset=TestSer.objects.all(),
                fields=('name',),
                message="名称已存在"
            )
        ]

3)views.py

from rest_framework.views import APIView
from .serializers import *
from rest_framework.response import Response
from .models import *


class SerTestApiView(APIView):

    def get(self, request, *args, **kwargs):
        qs = TestSer.objects.all()
        ser = TestSerSerializer(instance=qs, many=True)
        return Response({'msg': 'success', 'data': ser.data})

    def post(self, request, *args, **kwargs):
        ser = TestSerSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        return Response(ser.errors)

4)urls.py配置
2、SerializerMethodField、PrimaryKeyRelatedField、StringRelatedField、SlugRelatedField
1)models.py

class Book(models.Model):
    title = models.CharField(max_length=20)
    author = models.ManyToManyField(to='author')
    publish = models.ForeignKey('publish', on_delete=models.CASCADE, default='', related_name='pub')

    def __str__(self):
        return self.title


class Author(models.Model):
    name = models.CharField(max_length=10)
    age = models.IntegerField()


class Publish(models.Model):
    p_name = models.CharField(max_length=20)
    p_addr = models.CharField(max_length=50)

2)serializers.py

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = "__all__"


class PublishSerializer(serializers.ModelSerializer):
    # # PrimaryKeyRelatedField是通过model中外键的related_name找到关系,然后取到model中取到主键
    # pub = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    # # StringRelatedField是通过model中外键的related_name找到关系,然后取到model中定义的方法__str__返回的值
    pub = serializers.StringRelatedField(many=True, read_only=True)
    # # SlugRelatedField是通过model中外键的related_name找到关系,然后取到对应slug_field值,注意pub这个名字一定要和model中的related_name一致
    # pub = serializers.SlugRelatedField(many=True,read_only=True,slug_field='title')
    class Meta:
        model = Publish
        fields = ('p_name','pub')


class BookSerializer(serializers.ModelSerializer):
    # publish = serializers.CharField(source='publish.p_name')  # 外键、一对多可以用点的方式
    author = serializers.SerializerMethodField()  # 如果是多对多,必须自定义才行
    # 可以直接将上面PublishSerializer内嵌到当前序列化类中,这样当前序列化类就拥有了PublishSerializer所有的序列化后的数据
    publish = PublishSerializer(many=False)

    def get_author(self, obj):
        book_obj = Book.objects.get(pk=obj.pk)
        book_author = book_obj.author.all()
        res = []
        for bk in list(book_author.values()):
            res.append(bk.get('name'))
        return res
    class Meta:
        model = Book
        fields = "__all__"
        # depth = 1这是最简单的方式,返回所有存在的关系
        # depth = 1

3)views.py

class BookApiView(APIView):

    def get(self, request, *args, **kwargs):
        book_obj = Book.objects.all()
        ser = BookSerializer(book_obj, many=True)
        print(json.dumps(ser.data, ensure_ascii=False))
        return Response({'data': ser.data})


class PublishApiView(APIView):

    def get(self, request, *args, **kwargs):
        pub_obj = Publish.objects.all()
        ser = PublishSerializer(pub_obj, many=True)
        print(json.dumps(ser.data, ensure_ascii=False))
        return Response({'data': ser.data})

4)urls.py配置

文章评论

阿里云-云大使推广
阿里云-云服务器推广

微信公众号