drf--序列化组件

drf-->ModelSerializer:mysql

 

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

 

settings.pylinux

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__文件中git

import pymysql
pymysql.install_as_MySQLdb()
View Code

路由相关sql

    # 主路由
    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.pydjango

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

django 脚本化启动api

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.pyide

    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:post

    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': '删除失败',
            })

orm之 断关联多表关系

    1、外键位置:
        一对多 - 外键放多的一方
        一对一 - 从逻辑正反向考虑,如做者表与做者详情表,做者删除级联删除详情,详情删除做者依旧存在,因此建议外键在详情表中
        多对多 - 外键在关系表中
        
    2、ORM正向方向连表查找:
        正向:经过外键字段 eg: author_detial_obj.author 
        反向:经过related_name的值 eg:author_obj.detail
        注:依赖代码见下方
        
    3、连表操做关系:
        1)做者删除,详情级联 - on_delete=models.CASCADE
        2)做者删除,详情置空 - null=True, on_delete=models.SET_NULL
        3)做者删除,详情重置 - default=0, on_delete=models.SET_DEFAULT
        4)做者删除,详情不动 - on_delete=models.DO_NOTHING
        注:拿做者与做者详情表举例
        
    4、外键关联字段的参数 - 如何实现 断关联、目前表间操做关系、方向查询字段
        i)做者详情表中的
        author = models.OneToOneField(
            to='Author',
            related_name='detail',
            db_constraint=False,
            on_delete=models.CASCADE
        )
        
        ii)图书表中的
        publish = models.ForeignKey(
            to='Publish',
            related_name='books',
            db_constraint=False,
            on_delete=models.DO_NOTHING,
        )
        authors = models.ManyToManyField(
            to='Author'
            related_name='books',
            db_constraint=False,
        )
    
    注:
        1.ManyToManyField不能设置on_delete,OneToOneField、ForeignKey必须设置on_delete(django1.x系统默认级联,可是django2.x必须手动明确)
        2.db_constraint 
            db_constraint          惟一约束
            db_constraint = True   方便查询 约束字段
            db_constraint = fales(*)  不约束字段 同时也能够查询,就是保留跨表查询的便利
        3.on_delete 外键的删除
            1.on_delete = CASCADE:这就是默认的选项,级联删除,你无需显性指定它
            2.on_delete = PROTECT:保护模式,若是采用该选项,删除的时候,会抛出ProtectedError错误
            3.on_delete = SET_NULL:置空模式,删除的时候,外键字段被设置为空
                注:前提就是blank=True, null=True,定义该字段的时候,容许为空
            4.on_delete = SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,    
            5.on_delete = DO_NOTHING: 该模式做者删除,详情不动
        4 related_name = 'xxx'  子表在主表中对应的外键属性,反向引用
相关文章
相关标签/搜索