• drf--序列化组件


    drf-->ModelSerializer:

    相关:
        1.setting配置;
        2.路由分发,路由相关;
        3.自定义异常处理;
        4.model相关;
        5.serializers序列化相关;
        6.view相关;
                       

    settings.py

    INSTALLED_APPS = [
        ...
        'rest_framework',
    ]
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'dg_proj',
            'USER': 'root',
            'PASSWORD': '123',
        }
    }
    LANGUAGE_CODE = 'zh-hans'
    TIME_ZONE = 'Asia/Shanghai'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = False
    MEDIA_URL
    = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

    项目名下__init__文件中

    import pymysql
    pymysql.install_as_MySQLdb()
    View Code

    路由相关

        # 主路由
        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'^api/', include('api.urls')),
            url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
        ]            
        
        #子路由
        urlpatterns = [
        url(r'^books/$', views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),
        url(r'^v2/books/$', views.V2Book.as_view()),
        url(r'^v2/books/(?P<pk>.*)/$', views.V2Book.as_view()),
        
        ]    

    model.py

         基表:存储有关数据库的信息的底层表,在数据库中首创的对象
            class BaseModel(models.Model):
                is_delete = modles.BooleanField(default=0)
                create_time = models.DateTimeField(auto_now_add=True)
                #作为基表的model不能再数据库中形成对应的表*****
                class Meta:
                    abstract = True

    class Book(BaseModel): name = models.CharField(max_length=64) price = models.DecimalField(max_digits=5, decimal_places=2) img = models.ImageField(upload_to='img', default='img/default.jpg') publish = models.ForeignKey( to='Publish', db_constraint=False, # 断关联 related_name='books', # 反向查询字段:publish_obj.books 就能访问所有出版的书 on_delete=models.DO_NOTHING, # 设置连表操作关系 ) authors = models.ManyToManyField( to='Author', db_constraint=False, related_name='books' ) # 序列化插拔式属性 - 完成自定义字段名完成连表查询 @property def publish_name(self): return self.publish.name @property def author_list(self): return self.authors.values('name', 'age', 'detail__mobile').all() class Publish(BaseModel): """name、address、is_delete、create_time""" name = models.CharField(max_length=64) address = models.CharField(max_length=64) class Meta: db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(BaseModel): """name、age、is_delete、create_time""" name = models.CharField(max_length=64) age = models.IntegerField() class Meta: db_table = 'author' verbose_name = '作者' verbose_name_plural = verbose_name def __str__(self): return self.name class AuthorDetail(BaseModel): """mobile, author、is_delete、create_time""" mobile = models.CharField(max_length=11) author = models.OneToOneField( to='Author', db_constraint=False, related_name='detail', on_delete=models.CASCADE, ) class Meta: db_table = 'author_detail' verbose_name = '作者详情' verbose_name_plural = verbose_name def __str__(self): return '%s的详情' % self.author.name

    admin.py

        from . import models
        admin.site.register(models.Book)
        admin.site.register(models.AuthorDetail)
        admin.site.register(models.Author)
        admin.site.register(models.Publish)        

    django 脚本化启动

    import os
    os.environ.setdefault(
    "DJANGO_SETTINGS_MODULE", "drfday1.settings") django.setup()

    exception.py:自定义异常处理器

      from rest_framework.views import excepthon_handler as drf_excepthon_handler
        from rest_framework.views import Response
        from rest_framework import status
        
        def exception_handler(exc,context):
            #drf的 exception_handler做基础处理
            response = drf_exception_handler(exc,conteax)
            
            if response is None:
                print('%s-%s-%s'%(context['view'],context['request'].method,exc))
                
                return     Response({
                    'detail':'服务器错误'
                },status=status.HTTP_500_INTERNAL_SERVER_ERROR,exception=True)
            return response

    Serializer.py

        from rest_frameword.serializers import ModelSerializer,serializerMethodField
        from . import models
        from rest_frameword.excepthon import ValidationError
        #序列化
        class BookModelSerializer(ModelSerializer):
            class Meta:
                #(*****)
                #序列化类关联的model类
                model = models.Book
                #参与序列化的字段
                fields = ('name','price','publish','author')    
                #(***)
                #所有字段
                fields = '__all__'
                #exclude 是除过fields查出的所有字段,与fields不能共存
                exclude = ('id','img')
                #连表查询深度
                depth=1        
    
        #反序列化            
        class BookModelDeserializer(ModelSerializer):
            class Meta:
                model = models.Book
                # fields = ('name','price','publish','authors')
                # extra_kwargs 用来完成反序列化字段的 系统校验规则
                fields = '__all__'
                extra_kwargs ={
                    'name':{
                        'write_only':True,
                        'min_length':1,
                        'error_messages':{
                            'required': '必填项',
                            'min_length': '不够',
                        }
                    }
                }
    
            单个字段的验证
            1.在序列化器里定义校验字段的钩子方法   validate_字段
            2.获取字段的数据
            3.验证不通过,抛出异常  raise serializers.ValidationError("校验不通过的说明")
            4.验证通过,直接返回字段数据
            def validate_title(self,value):
                # 判断value是否含有敏感字段
                if "xx" in value:
                    # 存在敏感字段,抛出异常并附上自定义的原因
                    raise serializers.ValidationError("该字段含有敏感词")
                # 不存在,则直接返回
                    return value
            多个字段的验证
            1.在序列化器定义validate方法
            2.attrs是所有数据组成的字典
            3.不符合抛出异常 raise serializers.ValidationError("校验不通过的说明")
            def validate(self, attrs):# arrrs是数据组成的字典 
                # 判断linux的数是否在linux分类
                if "linux" in attrs.get('title') and attrs['category_post'] == 2:
                    return attrs
                else:
                    raise serializers.ValidationError("图书与分类不一致")            
            自定义验证器
            使用:在字段添加   validators=[自定义验证器,]
            def my_validate(value):
                if "xxx" in value:
                    raise serializers.ValidationError("该字段包含敏感词!!!")
                else:
                    return value        
            title = serializers.CharField(max_length=32,validators=[my_validate,])             # 使用自定义验证器        
    
        #序列化与反序列化整合版 (终极版本)
        class V2BookModelSerializer(ModelSerializer):
            """
            1) fields中设置所有序列化与反序列化字段
            2) extra_kwargs划分只序列化或只反序列化字段
                write_only:只反序列化
                read_only:只序列化
                自定义字段默认只序列化(read_only)
            3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则
            """
            class Meta:
                model = models.Book
                fields = ('name','price','img','author_list','publish_name','publish','authors')
                extra_kwargs = {
                    'name':{
                        'required':True,
                        'min_length':3,
                        'error_messages':{
                            'required':'必填项',
                            'min_length':'最少3'
                        }
                    },
                    'publish':{'write_only':True},
                    'authors':{'write_only':True},
                    'img':{'read_only':True},
                    'author_list':{'read_only':True},
                    'publish_name':{'read_only':True},
                }
    
                #单字段校验
                def validate_name(self,value):
                    if 'xx' in value.lower():
                        raise ValidationError('书名不符合规则')
                    return value
                #多字段校验
                def validate(self,attrs):
                    publish = attrs.get('publish')
                    name = attrs.get('name')
                    if models.Book.objects.filter(name=name,publish=publish):
                        raise ValidationError('这本书已存在')
                    return attrs

    views.py:

        from . importo models,serializers
        from rest_framework.views import APIView
        from rest_framework.response import Pesponse
        
        class Books(APIView):# 继承rest_framework的APIView    
            def get(self,request,*args,**kwargs):
                pk = kwargs.get('pk')
                if pk:
                    try:
                        book_obj = models.Book.objects.get(pk=pk,is_delete=False)
                        book_data = serializers.BookModelSerializer(book_obj).data
                    except:
                        return Response({
                            'status':1,
                            'msg':'没有这本书'
                        })
                else:
                    book_query = models.Book.objects.all().filter(is_delete=False)
                    book_data = serializers.BookModelSerializer(book_query,many=True).data
                return Response({
                    'status':0,
                    'msg':'ok',
                    'results':book_data
                })
            def post(self,request,*args,**kwargs):
                request_data = request.data
                book_ser = serializers.BookModelDeserializer(data=request_data)
                # 当校验失败,马上终止当前视图方法,抛异常返回给前台
                book_ser.is_valid(raise_exception=True)
                book_obj = book_ser.save()# 调用 create
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': serializers.BookModelSerializer(book_obj).data
                })
        
        class V2books(APIView):
            #查
            def get(self,request,*args,**kwargs):
                pk = kwargs.get('pk')
                if pk:
                    try:
                        book_obj = models.Book.objects.filter(pk=pk,is_delete=False)
                        book_data = serializers.V2BookModelSerializer(book_obj).data
                    except:
                        return Response({
                            'status': 1,
                            'msg': '书籍不存在'
                        })
                else:
                    book_list = models.Book.objects.all().filter(is_delete=False)
                    book_data = serializers.V2BookModelSerializer(book_list,many=True).data
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': book_data
                })
    
            # 单增:传的数据是与model对应的字典
            # 群增:传的数据是 装多个 model对应字典 的列表
            def post(self,request,*args,**kwargs):
                request_data = request.data
                if isinstance(request_data,dict):
                    many = False
                elif isinstance(request_data, list):
                    many = True
                else:
                    return Response({
                        'status': 1,
                        'msg': '数据有误',
                    })
                book_ser = serializers.V2BookModelSerializer(data=request_data,many=many)
                book_ser.is_valid(raise_exception=True)
                book_result = book_ser.save()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': serializers.V2BookModelSerializer(book_result, many=many).data
                })
    
            # 单删:有pk
            # 群删:有pks   |  {"pks": [1, 2, 3]}
            def delete(self,request,*args,**kwargs):
                pk = kwargs.get('pk')
                if pk:
                    pks = [pk]
                else:
                    pks = request.data.get('pks')
                if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True):
                    return Response({
                        'status': 0,
                        'msg': '删除成功',
                    })
                return Response({
                    'status': 1,
                    'msg': '删除失败',
                })
  • 相关阅读:
    HZOI20190906模拟38 金,斯诺,赤
    HZOI20190903模拟36 字符,蛋糕,游戏
    HZOI20190902模拟35题解
    HZOI20190829模拟33题解
    HZOI20190828模拟32题解
    HZOI20190823模拟31题解
    HZOI20190823 C magic
    HZOI20190822模拟29题解
    HZOI20190821模拟28题解
    P2925 [USACO08DEC]干草出售Hay For Sale 题解
  • 原文地址:https://www.cnblogs.com/wyf20190411-/p/11690770.html
Copyright © 2020-2023  润新知