restframework——序列化组件

models.py

from django.db import models

# Create your models here.
__all__ = ["Book", "Publisher", "Author"]


class Book(models.Model):
    title = models.CharField(max_length=32)
    CHOICES = ((1, "Python"), (2, "Linux"), (3, "go"))
    category = models.IntegerField(choices=CHOICES, null=True, blank=True)
    pub_time = models.DateField()
    publisher = models.ForeignKey(to="Publisher")
    authors = models.ManyToManyField(to="Author")


class Publisher(models.Model):
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title


class Author(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name

  urls.py

from django.conf.urls import url, include
from .views import BookView,BookEditView

urlpatterns = [
    url(r'^book/$', BookView.as_view()),
    url(r'^book/(?P<id>\d+)', BookEditView.as_view()),

]

 

序列化 post请求(新增数据)

 视图函数

from rest_framework.response import Response
from djangoDemo.models import Book
from .serializers import BookSerializer

class BookView(APIView):
    def get(self, request):
        book_queryset = Book.objects.all()
        # [book_obj, ]
        # 用序列化器进行序列化
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)

    # 新增数据
    def post(self, request):
        # 从前端得到的请求数据
        book_obj = request.data
        # print(book_obj)
        # BookSerializer(data=book_obj) 反序列化的时候必须指定data=
        ser_obj = BookSerializer(data=book_obj)
        # 对数据进行校验
        if ser_obj.is_valid():
            ser_obj.save()
            print(ser_obj.validated_data)
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)

 

 序列化器: serializers.py

一.声明序列化类

from rest_framework import serializers
from djangoDemo.models import Book


class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)

 

二.外键关系的序列化

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32, validators=[my_validate,])
    pub_time = serializers.DateField()
    category = serializers.CharField(source="get_category_display", read_only=True)
    post_category = serializers.IntegerField(write_only=True)

    publisher = PublisherSerializer(read_only=True)
    # 内部通过外键关系的id找到了publisher_obj
    # PublisherSerializer(publisher_obj)
    authors = AuthorSerializer(many=True, read_only=True)

 

反序列化

当前端给我们发post的请求的时候~前端给我们传过来的数据~我们要进行一些校验然后保存到数据库~

这些校验以及保存工作,DRF的Serializer也给我们提供了一些方法了~~

首先~我们要写反序列化用的一些字段~有些字段要跟序列化区分开~~

Serializer提供了.is_valid()  和.save()方法~~

-- 正序和反序列化字段不统一
-- required=False 只序列化不走校验
-- read_only=True  只序列化用
-- write_only=True  只反序列化用
-- 重写create方法

-- 验证通过返回ser_obj.validated_data

-- 验证不通过返回ser_obj.errors

 

class BookSerializer(serializers.Serializer):
    # required=False 表示不做校验
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32,validators=[my_validate,])
    pub_time = serializers.DateField()
    category = serializers.CharField(source="get_category_display", read_only=True)

    publisher = PublisherSerializer(read_only=True)
    authors = AuthorSerializer(many=True, read_only=True)

    post_category = serializers.IntegerField(write_only=True)
    publisher_id = serializers.IntegerField(write_only=True)
    author_list = serializers.ListField(write_only=True)

    def create(self, validated_data):
        # print(validated_data)
        # 这是validated_data
        '''
         {
        'title': '侠客行', 'pub_time': datetime.date(2018, 11, 14), 'post_category': 1, 'publisher_id': 1, 'author_list': [1, 2]
        }
        '''
        book_obj = Book.objects.create(title=validated_data['title'], pub_time=validated_data['pub_time'],
                                       category=validated_data['post_category'],
                                       publisher_id=validated_data['publisher_id'])
        # 多对多字段添加
        book_obj.authors.add(*validated_data['author_list'])
        return book_obj
View Code

 

反序列化put/patch请求(更新数据)

视图函数 views.py

class BookEditView(APIView):
    def get(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(book_obj)
        return Response(ser_obj.data)
    # put post 都是反序
    # 更新数据
    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)

 

序列化器 serializers.py

-- 重写update方法
-- ser_obj = BookSerializer(instance=obj, data=request.data, partial=True)
-- 验证通过返回ser_obj.validated_data
-- 验证不通过返回ser_obj.errors 

 

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

 

验证

单个字段的验证  权重 222
    def validate_title(self, value):
        print(2222)
        # value就是title的值 对value处理
        if "python" not in value.lower():
            raise serializers.ValidationError("标题必须含有python")

多个字段的验证  权重 333
    def validate(self, attrs):
        print(33333)
        # attrs 字典有你传过来的所有的字段  >>>>OrderedDict([('title', 'python'), ('post_category', 2)])
        print(attrs)
        if "python" in attrs["title"].lower() or attrs["post_category"] == 1:
            return attrs
        else:
            raise serializers.ValidationError("分类或标题不合符要求")

自定义的验证  权重 111
def my_validate(value):
    print(111, value)
    if '敏感信息' in value.lower():
        raise serializers.ValidationError('有敏感词汇')
    return value

        配置:  给字段加validators=[my_validate]
            title = serializers.CharField(max_length=32,validators=[my_validate,]) 
       

ModelSerializer

现在我们已经清楚了Serializer的用法,会发现我们所有的序列化跟我们的模型都紧密相关~

那么,DRF也给我们提供了跟模型紧密相关的序列化器~~ModelSerializer~~

  -- 它会根据模型自动生成一组字段

  -- 它简单的默认实现了.update()以及.create()方法

一.定义一个ModelSerializer序列化器

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"
        # fields = ["id", "title", "pub_time"]
        # exclude = ["user"]
        # 分别是所有字段 包含某些字段 排除某些字段

外键关系的序列化

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"
        # fields = ["id", "title", "pub_time"]
        # exclude = ["user"]
        # 分别是所有字段 包含某些字段 排除某些字段
        depth = 1
# depth 代表找嵌套关系的第几层

外键关系序列化

 

方法字段-- SerializerMethodField() 

def get_字段名称(self, obj):
    obj  每次序列化的模型对象
    return 自定义的数据

 

class BookSerializer(serializers.ModelSerializer):
    # category_display = serializers.SerializerMethodField(read_only=True)
    # # publisher_info = serializers.SerializerMethodField(read_only=True)
    # # authors_info = serializers.SerializerMethodField(read_only=True)
    # def get_category_display(self,obj):
    #     return obj.get_category_display()
    publisher_info = serializers.SerializerMethodField(read_only=True)
    category_info = serializers.SerializerMethodField(read_only=True)
    authors_info = serializers.SerializerMethodField(read_only=True)

    # category = serializers.SerializerMethodField()

    def get_publisher_info(self, obj):
        print(111, obj)
        publisher_obj = obj.publisher
        return {'id': publisher_obj.id, 'title': publisher_obj.title}

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

    def get_authors_info(self, obj):
        authors_querset = obj.authors.all()
        return [{"id": author.id, "name": author.name} for author in authors_querset]

Meta中其它关键字参数

class BookSerializer(serializers.ModelSerializer):
    chapter = serializers.CharField(source="get_chapter_display", read_only=True)

    class Meta:
        model = Book
        fields = "__all__"
        # fields = ["id", "title", "pub_time"]
        # exclude = ["user"]
        # 分别是所有字段 包含某些字段 排除某些字段
        depth = 1
        read_only_fields = ["id"]
        extra_kwargs = {"title": {"validators": [my_validate,]}}

Meta中参数

 

posted @ 2018-11-15 21:56  shuai1993  阅读(260)  评论(0编辑  收藏  举报