lf-M9-cp2-04 序列化

将后端数据库中的信息用json的格式传给前端

Django-JsonResponse序列化

import json

from django.http import HttpResponse,JsonResponse

from django.views import View
from .models import Book

class BookView(View):
    def get(self,request):
        book_list = Book.objects.values("id","title","pub_time")
        book_list = list(book_list)

        ret = json.dumps(book_list,ensure_ascii=False)

        return HttpResponse(ret)

 

日期格式数据会无法被json序列化后通过 HttpResponse 发送

 

利用 JsonResponse 可序列化费字典类型的对象

def get(self,request):
        book_list = Book.objects.values("id","title","pub_time")
        book_list = list(book_list)
     return JsonResponse(book_list,safe=False,json_dumps_params={"ensure_ascii":False}) #ensure_ascii 防止乱码

最终取出所有信息

class BookView(View):

    # 第一版 用.values JsonResponse实现序列化
    def get(self, request):
        book_list = Book.objects.values("id", "title", "category", "pub_time", "publisher")
        book_list = list(book_list)
        ret = []
        for book in book_list:
            publisher_id = book["publisher"]
            publisher_obj = Publisher.objects.filter(id=publisher_id).first()
            book["publisher"] = {
                "id": publisher_id,
                "title": publisher_obj.title
            }
            ret.append(book)
        # ret = json.dumps(book_list, ensure_ascii=False)
        return JsonResponse(ret, safe=False, json_dumps_params={"ensure_ascii": False}) 

Django-serializers序列化

from django.core import serializers
 
 
class BookView(View):
    # 第二版 用django serializers实现序列化
    def get(self, request):
        book_list = Book.objects.all()
        ret = serializers.serialize("json", book_list, ensure_ascii=False)
        return HttpResponse(ret)

序列化数据不完整,

image

DRF序列化

安装 pip install djangorestframework

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'SerDemo',
    'rest_framework',
]
注册到项目的app里面

编写序列化的类

from rest_framework import serializers

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
    category = serializers.ChoiceField(choices=CHOICES,source="get_category_display")
    pub_time = serializers.DateField()

视图函数

from rest_framework.views import APIView

from rest_framework.response import Response
from .serializers import BookSerializer  # 导入序列化类
class BookView(APIView):

    def get(self, request):
        book_obj = Book.objects.first()
        ret = BookSerializer(book_obj)
        # book_list = Book.objects.all()  # 拿到所有的对象
        # ret = BookSerializer(book_list, many=True)
        return Response(ret.data)

image

含外键数据的序列化

from rest_framework import serializers

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()
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
    category = serializers.ChoiceField(choices=CHOICES, source="get_category_display")
    pub_time = serializers.DateField()

    publisher = PublisherSerializer()
    author = AuthorSerializer(many=True)

image

DRF反序列化

将前端传过来的数据进行反序列化,然后保存到数据库

read_only=True #序列化
write_only=True #反序列化数据
 
前端传过来的数据样式
{
    "title": "Alex的使用教程",
    "w_category": 1,
    "pub_time": "2018-10-09",
    "publisher_id": 1,
    "author_list": [1, 2]
}

接受Post前端传过来的数据,必须在serialise类定义create方法

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): # 创建数据,接受post 数据
        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

定义 post 方法接受前端传过来的数据

class BookView(APIView):

    def get(self, request):
        # book_obj = Book.objects.first()
        # ret = BookSerializer(book_obj)
        book_list = Book.objects.all()
        ret = BookSerializer(book_list, many=True)
        return Response(ret.data)

    def post(self, request):
        print(request.data)
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)  #校验成功,反回
        else:
            return Response(serializer.errors)

post数据

image

反回的结果

image

DRF的PUT请求部分验证

from django.urls import path, include
from .views import BookView, BookEditView

urlpatterns = [
    path('list', BookView.as_view()),
    path('retrieve/<int:id>', BookEditView.as_view()),

]
class BookEditView(APIView):

    def get(self, request, id):  # 获取单条数据
        book_obj = Book.objects.filter(id=id).first()
        ret = BookSerializer(book_obj)
        return Response(ret.data)

    def put(self, request, id):  # 修改数据
        book_obj = Book.objects.filter(id=id).first()
        serializer = BookSerializer(book_obj, data=request.data, partial=True) # partial=True # 支持部分验证
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)

    def delete(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        book_obj.delete()
        return Response("")

查看单条数据,获取id为4的数据

image

修改数据

前端传过来的数据

data = {
"title": "Alex的使用教程2"
}

对修改的数据进行序列化处理 update 方法

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 update(self, instance, validated_data):   # 处理 put 更新数据
        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

image

反回的结果

image

DRF的验证

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):  # 处理 put 更新数据
        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
BookSerializer
    def validate_title(self, value):   # 对传过来的title进行校验
        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("分类以及标题不符合要求")

image

image

image

image

自定义验证器

当有重叠校验器时自定义的验证器权重更高

def my_validate(value):  # 自定义验证器,权重更高,用在需要校验数据的地方
    if "敏感信息" in value.lower():
        raise serializers.ValidationError("不能含有敏感信息")
    else:
        return value
 
使用
title = serializers.CharField(max_length=32, validators=[my_validate])

ModelSerializer序列化

image

image

# depth = 1

image

class BookSerializer(serializers.ModelSerializer):
    category = serializers.CharField(source="get_category_display")
    class Meta:
        model = Book  # 对应的 model
        # fields = ["id", "title", "pub_time"]
        fields = "__all__"  # 所有字段
        depth = 1  # 外键深度为1

image

拿到了较多的冗余字段

通过 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}

ModelSerializer反序列化

ModelSerializer 默认已经帮我们做了反序列化(不用写 create 方法)接受post 数据

image

image


def my_validate(value): # 自定义验证器,权重更高,
if "敏感信息" in value.lower():
raise serializers.ValidationError("不能含有敏感信息")
else:
return value
 
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} # category = serializers.CharField(source="get_category_display") class Meta: model = Book # 对应的 model # fields = ["id", "title", "pub_time"] fields = "__all__" # depth = 1 # 字段的额外参数, "write_only": True 反序列化的时候显示 extra_kwargs = {"category": {"write_only": True}, "publisher": {"write_only": True}, "author": {"write_only": True}}
from rest_framework import serializers
from .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)


#
# # 传过来的书籍对象数据
# book_obj = {
#     "title": "Alex的使用教程",
#     "w_category": 1,
#     "pub_time": "2018-10-09",
#     "publisher_id": 1,
#     "author_list": [1, 2]
# }
#
# data = {
#     "title": "Alex的使用教程2"
# }


def my_validate(value):  # 自定义验证器,权重更高,
    if "敏感信息" in value.lower():
        raise serializers.ValidationError("不能含有敏感信息")
    else:
        return value


# 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):  # 处理 put 更新数据
#         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):  # 对传过来的title进行校验
#         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}

    # category = serializers.CharField(source="get_category_display")
    class Meta:
        model = Book  # 对应的 model
        # fields = ["id", "title", "pub_time"]
        fields = "__all__"
        # depth = 1

        # 字段的额外参数, "write_only": True 反序列化的时候显示
        extra_kwargs = {"category": {"write_only": True}, "publisher": {"write_only": True},
                        "author": {"write_only": True}}
serializers.py

序列化组件小结

猜你喜欢

转载自www.cnblogs.com/wenyule/p/10425487.html
今日推荐