ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多表关联的序列化和反序列化

2022-01-04 11:34:13  阅读:170  来源: 互联网

标签:多表 ser models self publish 关联 序列化 data class


1 多表关联的序列化和反序列化

1.1 序列化类

from rest_framework import serializers
from .models import Book, Publish, Author, AuthorDetail


# class BookSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Book
#         fields = ['id', 'title', 'price', 'publish', 'authors', 'publish_detail',
#                   'author_detail']  # 字段可以是属性,也可以是方法(是方法返回值)
#         # depth=1  # 深度查一层,官方建议不大于10,正常不超过3,不建议用
#         extra_kwargs = {'publish': {'write_only': True},
#                         'authors': {'write_only': True},
#                         'publish_detail': {'read_only': True},
#                         'author_detail': {'read_only': True}
#                         }
#     # 把publish显示出版社的名字和地址
#     # 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
#     # 方法二:在序列化类中写
# class BookSerializer(serializers.ModelSerializer):
#     class Meta:
#         model = Book
#         # 写在BookSerializer的类属性,也需要在fields中注册一下
#         fields = ['id', 'title', 'price', 'publish', 'authors', 'publish_detail',
#                   'author_detail']  # 字段可以是属性,也可以是方法(是方法返回值)
#         # depth=1  # 深度查一层,官方建议不大于10,正常不超过3,不建议用
#         extra_kwargs = {'publish': {'write_only': True},
#                         'authors': {'write_only': True},
#                         }
#
#     # 把publish显示出版社的名字和地址
#     # 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
#     # 方法二:在序列化类中写
#     publish_detail = serializers.SerializerMethodField(
#         read_only=True)  # 这个字段需要配合一个方法,方法必须叫get_字段名,方法返回什么,publish_detail就是什么
#
#     def get_publish_detail(self, obj):
#         # obj就是当前序列化到的对象,就是book对象
#         return {'name': obj.publish.name, 'address': obj.publish.address}
#
#     author_detail = serializers.SerializerMethodField(read_only=True)
#
#     def get_author_detail(self, obj):
#         author_list = obj.authors.all()
#         author_dict_list = []
#         for author in author_list:
#             author_dict_list.append({'name': author.name, 'sex': author.get_sex_display()})
#         return author_dict_list

class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publish
        # fields = ['id']
        fields = '__all__'


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


class AuthorDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = AuthorDetail
        fields = "__all__"


class BookSerializer(serializers.ModelSerializer):
    publish = PublishSerializer()
    authors = AuthorSerializer(many=True)  # 多条,一定要加一个 many=True
    class Meta:
        model = Book
        # 写在BookSerializer的类属性,也需要在fields中注册一下
        fields = ['id', 'title', 'price', 'publish', 'authors']  # 字段可以是属性,也可以是方法(是方法返回值)
        # depth=1  # 深度查一层,官方建议不大于10,正常不超过3,不建议用
        extra_kwargs = {'publish': {'write_only': True},
                        'authors': {'write_only': True},
                        }

    # 把publish显示出版社的名字和地址
    # 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
    # 方法二:在序列化类中写
    # 方式三:通过子序列化


1.2 视图

from .models import Book, AuthorDetail, Author
from .seriazlizer import BookSerializer


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(data=ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)
        # ser.is_valid(raise_exception=True)


class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(data=ser.data)

    def put(self, request, pk):
        book = Book.objects.all().filter(pk=pk).first()  # 数据不存在,None,如果instance是None,ser.save-->新增

        ser = BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        res = Book.objects.all().filter(pk=pk).delete()  # 返回影响的行数的元组
        print(res)  #
        if res[0] >= 1:
            return Response()
        else:
            return Response('要删除的数据不存在')

1.3 模型层

from django.db import models


# 图书表    出版社   作者  作者详情    图书和作者的多对多表

#
# 一对多:关系一旦确立,关联字段写在多的一方
# 多对多:需要有中间表


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # on_delete:
    # models.CASCADE  # 级联删除
    # models.DO_NOTHING # 什么都不做
    # models.SET_DEFAULT #设置为默认值
    # models.SET_NULL    # 设置为空
    # models.SET         #可以写一个函数内存地址,删除的时候,触发这个函数执行
    publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
    authors = models.ManyToManyField(to='Author')

    # @property  # 加不加都行
    # def publish_detail(self):
    #     return {'name': self.publish.name, 'address': self.publish.address}
    #
    # # 作者详情 在列表套字典
    # def author_detail(self):
    #     # 获取所有作者
    #     author_list = self.authors.all()
    #     author_dict_list = []
    #     for author in author_list:
    #         author_dict_list.append({'name': author.name, 'sex': author.get_sex_display()})
    #     return author_dict_list


class Publish(models.Model):
    name = models.CharField(max_length=16)
    address = models.CharField(max_length=64)


class Author(models.Model):
    name = models.CharField(max_length=16)
    sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0)


class AuthorDetail(models.Model):
    mobile = models.CharField(max_length=11)
    # OneToOneField 本质就是  ForeignKey+unique
    author = models.OneToOneField(to='Author', on_delete=models.CASCADE)
    # author = models.ForeignKey(to='Author', on_delete=models.CASCADE,unique=True)

1.4 路由

urlpatterns = [
    #    path('admin/', admin.site.urls),
    path('publish/', views.PublishView.as_view()),
    path('publish/<int:pk>', views.PublishDetailView.as_view()),
    path('book/', views.BookView.as_view()),
    path('book/<int:pk>', views.BookDetailView.as_view()),
]

2 请求与响应

2.1 Request

# 属性:
request.data  # 基于django中的request进行的二次封装,可以从request.data获取所有的数据
request.query_params
request._request  原来的request
request.method  --->就是使用了原来的request的method  通过重写 __getattr__魔法方法实现的

# 默认情况下post提交数据,可以三种方式(form-data,urlencoded,json),都能处理
# 我们只允许接口接收json格式,其他格式不支持
# 方式一:全局配置,在配置文件中
REST_FRAMEWORK = {
    # 默认能够解析的编码方式
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',  # json的
        # 'rest_framework.parsers.FormParser', # urlencoded
        # 'rest_framework.parsers.MultiPartParser' # form-data
    )
}

# 局部配置:(视图类)
class PublishView(APIView):
    parser_classes = [FormParser,]  # 优先级更高
    
    
 # 优先级:先用视图类自己的,再用配置文件---》drf的默认配置

2.1 响应 Response

# 属性:
data:返回给前端的数据,可以是字典,列表,字符串
status:响应状态码,1xx 2xx 3xx 4xx 5xx
template_name : 不用,替换模板
headers=None  :响应头

#默认用浏览器可以看到页面,用postman可以看到jon
#只能显示json
# 方式一:全局配置,在配置文件中
REST_FRAMEWORK = {
    # 使用的渲染类
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        # 'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

# 局部配置:(视图类)
class PublishView(APIView):
    renderer_classes = [JSONRenderer,]
    
    
 # 优先级:先用视图类自己的,再用配置文件---》drf的默认配置
    

3 视图组件(重点)

3.1 两个视图基类

##### 通过继承GenericAPIView 写5个接口
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView  # 继承APIView,写了几个类属性
'''
# 类属性
queryset = None  # 所有数据
serializer_class = None # 序列化的类
lookup_field = 'pk'  # 查询单条转换器的字段

# 三个方法
self.get_queryset()   # 获取所有数据
self.get_serializer   # 获取序列化类
self.get_object()    # 获取单条
'''

from rest_framework.mixins import RetrieveModelMixin,ListModelMixin,CreateModelMixin
class PublishView(GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer


    def get(self, request):
        obj = self.get_queryset()
        ser = self.get_serializer(instance=obj, many=True)
        return Response(data=ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)
        # ser.is_valid(raise_exception=True)


class PublishDetailView(GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer
    def get(self, request, pk):
        obj = self.get_object()  # 获取单条,根据pk
        ser = PublishSerializer(instance=obj)
        return Response(data=ser.data)

    def put(self, request, pk):
        obj = self.get_object()  # 数据不存在,None,如果instance是None,ser.save-->新增

        ser = self.get_serializer(data=request.data, instance=obj)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        res = self.get_object().delete()  # 返回影响的行数的元组
        print(res)  #
        if res[0] >= 1:
            return Response()
        else:
            return Response('要删除的数据不存在')

标签:多表,ser,models,self,publish,关联,序列化,data,class
来源: https://www.cnblogs.com/long4275/p/15761865.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有