4、ModelSerializer序列化类.md

一、ModelSerializer序列化器

models.py,创建两张表

# 图书表
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)


# 出版社表
class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)

序列化类

新建一个serializer.py文件(也可以是其他名字),用于存放序列化类

from rest_framework import serializers
from app01 import models


# 序列化出版社表
class BookModelSerializer(serializers.ModelSerializer):
    # 指定和表的关系
    class Meta:
        model = models.Publish  # model是固定语句,Publish是表,表示这个序列化是序列化Publish表
        fields = '__all__'  # fields是固定语句,后面是表里的字段,表示需要序列化哪些字段
        # 还可以使用  fields = ['name', 'addr'] 表示序列化表里单独字段
        
        '''不需要重写create和update方法'''

路由层开放两个接口

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookDeteView.as_view()),
    path('pub/', views.PublishView.as_view()),
    path('pub/<int:pk>', views.PublishDeteView.as_view()),
]

视图层写逻辑

from rest_framework.views import APIView  # 导入APIView
from app01 import models  # 导入models表
from rest_framework.response import Response  # 导入DRF的Response,用于返回数据给前端
from app01.serializer import BookModelSerializer  # 导入序列化类


class PublishView(APIView):
    def get(self, request):  # 查询数据
        pub_list = models.Publish.objects.all()
        ser = BookModelSerializer(instance=pub_list, many=True)
        return Response(ser.data)

    def post(self, request):  # 新增数据
        ser = BookModelSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})
        else:
            return Response({'code': 500, 'msg': ser.errors})


class PublishDeteView(APIView):
    def get(self, request, pk):  # 通过主键查单个数据
        pub = models.Publish.objects.all().filter(pk).first()
        ser = BookModelSerializer(instance=pub)
        return Response(ser.data)

    def put(self, request, pk):  # 修改数据
        pub = models.Publish.objects.all().filter(pk=pk).first()
        ser = BookModelSerializer(instance=pub, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功', 'data': ser.data})
        else:
            return Response({'code': 500, 'msg': ser.errors})

    def delete(self, request, pk):  # 删除数据
        res = models.Publish.objects.filter(pk=pk).delete()
        if res:
            return Response({'code': 100, 'msg': '删除成功'})
        else:
            return Response({'code': 500, 'msg': '数据不存在'})

二、重写字段

需求:在所有出版社后加个 —HOT

# 方式一:在序列化类里加
class PubModelSerializer(serializers.ModelSerializer):
    # 指定和表的关系
    class Meta:
        model = models.Publish  # model是固定语句,Publish是表,表示这个序列化是序列化Publish表
        fields = '__all__'
    # 重写这个字段,会优先加载这个
    name = serializers.SerializerMethodField()

    def get_name(self, obj):
        return obj.name + '—HOT'

##################################################################################
    
# 方式二:在表模型中定义一个name_detail,在fields中写一些字段或方法
# 首先在模型类里写一个方法
class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)

    def name_detail(self):
        return self.name + '—HOT'
# 然后回到序列化类里
class PubModelSerializer(serializers.ModelSerializer):
    # 指定和表的关系
    class Meta:
        model = models.Publish  # model是固定语句,Publish是表,表示这个序列化是序列化Publish表
        fields = ['name', 'addr', 'name_detail']  # 把这个方法添加进去,否则不会序列化方法

    name_detail = serializers.CharField(read_only=True)  # 设置为只能序列化(实际上这个字段是个方法,可以不写)
    name = serializers.CharField(write_only=True)  # 设置为只能反序列化

extra_kwargs方法:可以对字段进行限制条件

# 序列化出版社表
class PublishModelSerializer(serializers.ModelSerializer):
    # 指定和表的关系
    class Meta:
        model = models.Publish  # model是固定语句,Publish是表,表示这个序列化是序列化Publish表
        fields = '__all__'  # fields是固定语句,后面是表里的字段,表示需要序列化哪些字段
        
        extra_kwargs = {'addr': {'max_length': 8, 'min_length': 3,'write_only':True}}
        # 限制Publish表的

三、局部钩子和全局钩子

字段除了自身的限制,我们还可以额外添加钩子进行反序列化验证数据

# 局部钩子:给某个字段再增加校验(固定用法),定义一个方法,名字为validate_字段名
	def validate_addr(self, item):
		if item.startswith('sb'):
		# 抛异常,不能以sb开头
			raise ValidationError('不能以sb开头')
		else:
			return item
'''局部钩子的缺陷,无法处理两张字段关联的校验,所以设计多个字段就得使用全局钩子'''
# 全局钩子
# 限制出版社的名字不能等于出版社地址
	def validate(self, attrs):
		name = attrs.get('name')
		addr = attrs.get('addr')
		if name == addr:
			raise ValidationError('name和addr不能一样')
    	else:
        	return attrs
posted @ 2021-09-05 15:43  黑影Poco  阅读(58)  评论(0)    收藏  举报