反序列化更新方法的使用

反序列化更新数据通过update()方法来实现

python代码如下:

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例更新数据"""
        instance.btitle = validated_data['btitle']
        instance.bread = validated_data['bread']
        instance.save()
        return instance

book_drf目录下serializer.py文件的完整python代码如下:

from rest_framework import serializers

from books.models import BookInfo


class HeroInfoSerializer(serializers.Serializer):
    # 英雄序列化器
    hname = serializers.CharField()
    hcomment = serializers.CharField()
    hbook = serializers.PrimaryKeyRelatedField(read_only=True)
    # hbook = serializers.StringRelatedField(label='图书')


# # 自定义序列化器
# class BookSerialzier(serializers.Serializer):
#     # 序列化返回字段
#     btitle = serializers.CharField()
#     bread = serializers.IntegerField()
#     bpub_date = serializers.DateField()
#     # 返回关联的英雄id   PrimaryKeyRelatedField
#     # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
#     # 返回关联英雄模型类的str方法值
#     # heroinfo_set = serializers.StringRelatedField(read_only=True, many=True)
#     # 注意事项:内嵌的序列化器必须放在前面
#     heroinfo_set = HeroInfoSerializer(many=True)
def about_100(value):
    if value == 100:
        raise serializers.ValidationError("评论量不能为100")


# 自定义序列化器
class BookSerialzier(serializers.Serializer):
    # 序列化返回字段
    btitle = serializers.CharField(max_length=20, min_length=5)
    bread = serializers.IntegerField(max_value=100, min_value=5)
    # 如果没有选项参数就是必传参数,默认值是required=True
    bpub_date = serializers.DateField()
    # 当required=False,可以不传递参数
    # bpub_date = serializers.DateField(required=False)
    # 当没有传递此字段时,使用的是默认值10,而不会报错
    bcomment = serializers.IntegerField(default=10, validators=[about_100])

    # 单一字段验证
    def validate_btitle(self, value):

        if value == 'python':
            raise serializers.ValidationError('书名不能是python')
        return value

    # 多个字段验证
    def validate(self, attrs):

        if attrs['bread'] < attrs['bcomment']:
            raise serializers.ValidationError('阅读量大于评论量')

        return attrs

    def create(self, validated_data):
        # 保存数据
        print(validated_data)
        book = BookInfo.objects.create(**validated_data)

        return book

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例更新数据"""
        instance.btitle = validated_data['btitle']
        instance.bread = validated_data['bread']
        instance.save()
        return instance

book_drf目录下views.py文件的完整python代码如下:

import json

from django.http import JsonResponse
from django.views import View

from book_drf.serializer import BookSerialzier
from books.models import BookInfo


class Books(View):
    def get(self, request):
        # 1、查询所有图书对象
        books = BookInfo.objects.all()
        ser = BookSerialzier(books, many=True)
        return JsonResponse(ser.data, safe=False)

    def post(self, request):
        # 1、获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2、验证数据
        ser = BookSerialzier(data=data_dict)
        ser.is_valid()  # 验证方法

        # 3、保存数据
        ser.save()
        # 4、返回结果
        return JsonResponse(ser.data)

    # def post(self, request):
    #     # 1获取前端数据
    #     data = request.body.decode()  # 得到一个json的字符串
    #     data_dict = json.loads(data)  # 转换成字典形式
    #     # 2验证数据
    #     ser = BookSerialzier(data=data_dict)
    #     ser.is_valid()  # 验证方法
    #     print(ser.validated_data)  # 获取验证后的字段数据
    #     # 3保存数据
    #     # 4返回结果
    #     return JsonResponse(ser.errors)


class Book(View):

    def get(self, request):
        book = BookInfo.objects.get(id=1)
        ser = BookSerialzier(book)

        return JsonResponse(ser.data)


class BookDRFView(View):
    """
        序列化更新数据代码
    """

    def put(self, request, pk):
        # 1、获取前端数据
        data = request.body.decode()
        data_dict = json.loads(data)
        # 2、验证数据
        try:
            book = BookInfo.objects.get(id=pk)
        except:
            return JsonResponse({'error': '错误信息'}, status=400)
        # 更新数据时,需要传入一个对象,如果没有传入book,反序列化的save将是新增数据
        ser = BookSerialzier(book, data=data_dict)
        ser.is_valid()
        # 字段错误提示信息
        # 例如:{'btitle': [ErrorDetail(string='Ensure this field has at least 5 characters.', code='min_length')]}
        print(ser.errors)
        """{'required': 'This field is required.', 'null': 'This field may not be null.', 'invalid': 'Invalid data. Expected a dictionary, but got {d
atatype}.'}"""
        print(ser.error_messages)
        # 3、更新数据
        ser.save()
        # 4、返回结果
        return JsonResponse(ser.data)

配置测试的路由信息

book_drf目录下urls.py文件的完整python代码如下:

from django.conf.urls import url
from . import views
urlpatterns = [
    # 配置查询所有图书路由
    url(r'^books_drf/$', views.Books.as_view()),
    # 配置查询一本书的路由
    url(r'^book_drf/$', views.Book.as_view()),
    # 配置反序列化更新数据
    url(r'^books_drf/(?P<pk>\d+)/$', views.BookDRFView.as_view()),
]