zoukankan      html  css  js  c++  java
  • ModelSerializer插拔式序列化

    建数据库

    >: mysql -uroot -p密码
    >: create database day83 charset=utf8;
    

    表分析

    书表Book:name price 				  create_time is_delete 			authors publish
    出版社表Publish:name address phone   create_time is_delete
    作者表Author:name icon telephone 	  create_time is_delete
    作者详情表AuthorDetail:age sex info   create_time is_delete 			  author
    

    表关系

    Book 与 Publish 一对多
    Book 与 Autho 多对多
    Author 与 AuthorDetail 一对一
    

    model类

    """
    外键处理:
    
    反向查询名字:related_name
    表关系:db_constraint + on_delete  
        db_constraint=False => 断开表关系
        on_delete=models.CASCADE  级联
        on_delete=models.SET_NULL, null=True  设置为空
        on_delete=models.SET_DEFAULT, default=0  设置成默认值0
        on_delete=models.DO_NOTHING  不处理
    注:多对多关系不需要明确on_delete
    """
    from django.conf import settings
    class BaseModel(models.Model):
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
        is_delete = models.BooleanField(verbose_name='是否删除', default=False)
        class Meta:
            # 有该属性的Model类不会完成数据库迁移产生一张表 - 基表
            abstract = True
    
    
    class Publish(BaseModel):
        name = models.CharField(verbose_name='出版社名', max_length=32)
        address = models.CharField(verbose_name='地址', max_length=64)
        phone = models.CharField(verbose_name='电话', max_length=32)
        class Meta:
            db_table = 'o_Publish'
            verbose_name = '出版社'
            verbose_name_plural = verbose_name
        def __str__(self):
            return self.name
    
    
    class Author(BaseModel):
        name = models.CharField(verbose_name='作者名', max_length=32)
        icon = models.FileField(upload_to='icon', default='icon/icon.jpg')
        telephone = models.CharField(verbose_name='电话', max_length=32)
        class Meta:
            db_table = 'o_Author'
            verbose_name = '作者'
            verbose_name_plural = verbose_name
        def __str__(self):
            return self.name
    
    class AuthorDetail(BaseModel):
        CHOICE_SEX = (
            (0, '男'),
            (1, '女')
        )
        age = models.IntegerField(verbose_name='年龄')
        sex = models.IntegerField(verbose_name='性别', choices=CHOICE_SEX, default=0)
        info = models.TextField(verbose_name='个人详情')
        author = models.OneToOneField(verbose_name='作者', to='Author', db_constraint=False, on_delete=models.CASCADE, related_name='detail')
        class Meta:
            db_table = 'o_AuthorDetail'
            verbose_name = '作者详情'
            verbose_name_plural = verbose_name
        def __str__(self):
            return self.author.name + '的详情'
    
    
    class Book(BaseModel):
        name = models.CharField(verbose_name='书名', max_length=32)
        price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2, default=66.66)
        authors = models.ManyToManyField(verbose_name='作者们', to='Author', db_constraint=False, related_name='books')
        publish = models.ForeignKey(verbose_name='出版社', to='Publish', db_constraint=False, on_delete=models.CASCADE,
                                    related_name='books')
    
        class Meta:
            db_table = 'o_Book'
            verbose_name = '书籍'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
        # 插拔字段 - 默认为read_only(不需要考虑反序列化),且不能修改
        @property
        def publish_name(self):
            return self.publish.name
    
        @property
        def publish_detail(self):
            from . import serializers
            return serializers.PublishesModelSerializer(self.publish).data
    
        @property
        def author_list(self):
            author_arr = []
            for author in self.authors.all():
                author_arr.append(author.name)
            return author_arr
    
        @property
        def author_detail_list(self):
            author_detail_arr = []
            for author in self.authors.all():
                author_dic = {}
                author_dic['name'] = author.name
                author_dic['age'] = author.detail.age
                author_dic['telephone'] = author.telephone
                # author.icon是对象类型,不能序列化
                author_dic['icon'] = settings.MEDIA_URL + str(author.icon)
                author_detail_arr.append(author_dic)
            return author_detail_arr
    

    配置media

    # settings.py 配置文件
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    
    # urls.py 中路由文件
    from django.conf.urls import url, include
    from django.contrib import admin
    from django.views.static import serve
    from django.conf import settings
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    ]
    

    Serializer序列化类配置

    from rest_framework import serializers
    from . import models
    
    
    class TempSerializer(serializers.Serializer):
        # 序列化()可以为空
        k1 = serializers.CharField()
        # 反序列化通常有校验的条件
        k2 = serializers.CharField(write_only=True, max_length=32, min_length=3, error_messages={
            'max_length': '超长',
            'min_length': '超短',
        })
        k3 = serializers.CharField()
    
    
    
    class AuthorsModelSerializer(serializers.ModelSerializer):
        class Meta:
            fields = ('name', 'icon', 'telephone')
            model = models.Author
    
    
    class PublishesModelSerializer(serializers.ModelSerializer):
        class Meta:
            fields = ('name', 'address', 'phone')
            model = models.Publish
            extra_kwargs = {}
    
    
    class BooksModelSerializer(serializers.ModelSerializer):
        # 自定义字段 不建议 书写在Serializer类中,迁移到Model类中
        # 在ModelSerializer类的class Meta中 fields 字段值不能为__all__,因为publish_name字段必须参与序列化
        # publish_name = serializers.SerializerMethodField()
        # def get_publish_name(self, book_obj):
        #     return book_obj.publish.name
    
        # 只可序列化,导致反序列化崩溃 用Model插拔式自定义字段完成连表深度查询
        # publish = PublishesModelSerializer()
    
        class Meta:
            # 关联的Model类
            model = models.Book
            # 提供该表所有与数据库表对应的字段,不能和exclude同时出现
            # fields = '__all__'
            # 刨除该表的某些字段 - 不常用
            # exclude = ('id', 'create_time', 'is_delete')
            # 外键自动深度查询 - 不常用
            # depth = 1
            # 自定义提供该表的哪些字段 - 重点:可以插拔Model类中自定义字段 - 插拔式
            fields = ('name', 'price', 'publish', 'authors', 'publish_name', 'publish_detail', 'author_list', 'author_detail_list')
    
            # 1)可以区分 序列化(read_only) 与 反序列化(write_only) 字段
            # 2)提供系统默认校验信息即校验失败信息
            extra_kwargs = {
                'publish': {
                    'write_only': True
                },
                'authors': {
                    'write_only': True
                },
                'publish_name': {
                    'read_only': True,
                },
                'price': {
                    # 数据库字段设置了默认值,也需要 反序列化 时必须提供该字段
                    'required': True,
                    'error_messages': {
                        'required': '价格不能为空',
                    }
                },
                'name': {
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '太短',
                    }
                },
            }
    
        # ModelSerializer重写了 update 和 create,如果没有特殊业务要求,可以不需要再重写
        def create(self, validated_data):
            authors = validated_data.pop('authors')
            book_obj = models.Book.objects.create(**validated_data)
            # 关系表的新增
            # 关系表的相关操作 增add 删remove 改set 清空clear
            book_obj.authors.add(*authors)
            return book_obj
    
        # def update(self, instance, validated_data):
        #     return instance
    

    Views视图层配置

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    from . import models, serializers
    from utils.response import APIResponse
    class BooksAPIView(APIView):
        # 获取所有
        def get(self, request, *args, **kwargs):
            books_query = models.Book.objects.all()
            books_data = serializers.BooksModelSerializer(books_query, many=True).data
    
            return APIResponse(0, 'ok', books_data)
    
        # 新增一个
        def post(self, request, *args, **kwargs):
            request_data = request.data
            book_ser = serializers.BooksModelSerializer(data=request_data)
    
            if book_ser.is_valid():
                book_obj = book_ser.save()
                return Response({
                    'status': 1,
                    'msg': 'failed',
                    'results': serializers.BooksModelSerializer(book_obj).data
                })
            else:
                return Response({
                    'status': 1,
                    'msg': 'failed',
                    'results': book_ser.errors
                })
    
        # 修改一个
        def put(self, request, *args, **kwargs):
            pk = kwargs.get('pk', 1)
            book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
            book_ser = serializers.BooksModelSerializer(instance=book_obj, data=request.data)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': serializers.BooksModelSerializer(book_obj).data
                })
            else:
                return Response({
                    'status': 1,
                    'msg': 'failed',
                    'results': book_ser.errors
                })
    
        # 删除一个 /books/1/ | 删除多个 /books/  数据[1, 2]
        def delete(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:
                pks = [pk]
            else:
                pks = request.data
            delete_rows = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
            if delete_rows != 0:
                return APIResponse(0, 'ok')
            return APIResponse(1, '删除失败')
    
    
    
    class AuthorsAPIView(APIView):
        # 获取所有
        def get(self, request, *args, **kwargs):
            authors_query = models.Author.objects.all()
            authors_data = serializers.AuthorsModelSerializer(authors_query, many=True).data
    
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': authors_data
            })
    
    
    class PublishesAPIView(APIView):
        # 获取所有
        def get(self, request, *args, **kwargs):
            publishes_query = models.Publish.objects.all()
            publishes_data = serializers.PublishesModelSerializer(publishes_query, many=True).data
    
            # return Response({
            #     'status': 0,
            #     'msg': 'ok',
            #     'results': publishes_data
            # })
    
            from utils.response import APIResponse
            return APIResponse(0, 'ok', result=123,
                               headers={
                'Token': 'as12df.88og5z.qw12cv'
            }, status=status.HTTP_200_OK)
    
    """ Response类
        data:要返回给前台的数据
        status:响应的网络状态码
        template_name:drf也可以渲染页面
        headers:响应头
        exception:异常信息
        content_type:响应的数据类型,接口默认application/json
        
    def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
                 
        return Response({
                'status': 0,
                'msg': 'ok',
                'results': publishes_data
            }, headers={
                'Token': 'as12df.88og5z.qw12cv'
            }, status=status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED)
            
    
    from utils.response import APIResponse
            return APIResponse(0, 'ok', result=123,
                               headers={
                'Token': 'as12df.88og5z.qw12cv'
            }, status=status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED)
    """
    
  • 相关阅读:
    with check option(视图 )
    @@ERROR
    事务处理
    含有自增序列的表中使用truncate与delete的不同结果
    Oracle中的通配符
    Java方法重载
    java递归方法
    Oracle中的for语句
    Uboot 2014.07 makefile分析
    linux内核目录结构
  • 原文地址:https://www.cnblogs.com/huanghongzheng/p/11373748.html
Copyright © 2011-2022 走看看