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': '删除失败',
            })
原文地址:https://www.cnblogs.com/wyf20190411-/p/11690770.html