zoukankan      html  css  js  c++  java
  • drf 序列化组件

    准备:

     配置: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')
    
    REST_FRAMEWORK = {
    # 全局配置异常模块
        'EXCEPTION_HANDLER': 'api.exception.exception_handler',
    }

    任何__init__文件

    import pymysql
    pymysql.install_as_MySQLdb()

    主路由

    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}),
    ]

    子路由

    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^books/$',views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$',views.Book.as_view()),
    ]

    model 类  多表设计

    # 基表
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
        create_time = models.DateTimeField(auto_now_add=True)
    
        # 作为基表的model不能在数据库形成对应的表,设置abstract=True
        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 Meta:
            db_table = 'book'
            verbose_name = '书籍'
            verbose_name_plural = verbose_name
        def __str__(self):
            return self.name
    
    class Publish(BaseModel):
        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 = 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 = 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.Author)
    admin.site.register(models.AuthorDetail)
    admin.site.register(models.Book)
    admin.site.register(models.Publish)

    序列化

      序列化层:api/serializers.py

    from rest_framework.serializers import ModelSerializer,SerializerMethodField
    from rest_framework.exceptions import ValidationError
    from . import models
    # 可以单独作为Publish接口的序列化类,也可以作为Book序列化外键publish辅助的序列化组件
    class PublishModelSerializer(ModelSerializer):
        class Meta:
            model = models.Publish
            fields = ('name', 'address')
    
    class BookModelSerializer(ModelSerializer):
        # 自定义连表深度,子序列化方式 该方式不能参与反序列化,使用在序列化反序列化共存时
        publish = PublishModelSerializer()
    
        class Meta:
            # 序列化类关联的model类
            model = models.Book
            # 参与序列化的字段
            fields = ('name','price','img','author_list','publish')

    视图层:api/views.py

    from . import serializers
    class
    Book(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.filter(is_delete=False).all() book_data = serializers.BookModelSerializer(book_query,many=True).data return Response({ 'status': 0, 'msg': 'ok', 'results':book_data })

    反序列化

    路由层:api/urls.py

    urlpatterns = [
        url(r'^books/$',views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$',views.Book.as_view()),
    ]

    序列化层:api/serializers.py

    class BookModelDeserializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = {'name','price','publish','authors'}
            # extra_kwargs 用来完成反序列化字段 系统校验规则
            extra_kwargs = {
                'name': {
                    'required': True,
                    'min_length': 1,
                    'error_message': {
                        'required': '必填项',
                        'min_length': '太短'
                    }
                }
            }
    
        # 局部钩子
        def validate_name(self,value):
              # 书名不能含g 字符
            if 'g' in value.lower():
                raise ValidationError('该g书不能出版')
            return value
        # 全局钩子
        def validate(self, attrs):
            publish = attrs.get('publish')
            name = attrs.get('name')
            if models.Book.objects.filter(name=nam  e,publish=publish):
                raise ValidationError({'book':'该书已存在'})
            return attrs

    settings.py

    REST_FRAMEWORK = {
        # 全局配置异常模块
        'EXCEPTION_HANDLER': 'api.exception.exception_handler',
    }

    exception.py异常处理文件

    from rest_framework.views import exception_handler as drf_exception_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, context)
        # 为空,自定义二次处理
        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

    视图层:api/views.py

    class Book(APIView):
        def post(self, request, *args, **kwargs):
            request_data = request.data
            book_ser = serializers.BookModelDeserializer(data=request_data)
            # raise_exception=True:当校验失败,终止当前视图方法,抛出异常返回给前台
            book_ser.is_valid(raise_exception=True)
            book_obj = book_ser.save()
            return Response({
                'status':0,
                'msg':'ok',
                'results':serializers.BookModelDeserializer(book_obj).data
            })

    序列化与反序列化整合(重点)

      fields中设置所有序列化与反序列化字段,  extra_kwargs划分只序列化或只反序列化字段
          write_only:只反序列化
          read_only:只序列化
          自定义字段默认只序列化(read_only)

      设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则

    class V2BookModelSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = {'name','price','img','author_list','publish_name', 'publish', 'authors'}
            extra_kwargs = {
                'name':{
                    'required': True,
                    'min_length': 1,
                    'error_messages': {
                        'required':'必填项',
                        'min_length': '太短',
                    }
                },
                '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 'g' in value.lower():
                raise ValidationError('该g书不能出版')
            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({'book':'该书已存在'})
            return attrs

    视图层:api/views.py

    class V2Book(APIView):
      # 单查:有pk  群查: 无pk 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.V2BookModelSerializer(book_obj).data except: return Response({ 'status':1, 'msg':'书籍不存在' }) else: book_query = models.Book.objects.filter(is_delete=False).all() book_data = serializers.V2BookModelSerializer(book_query,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 }) def delete(self,request,*args,**kwargs):
        # 单删 有pk 群删 无pks 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':'删除失败' })
    dayehui
  • 相关阅读:
    php发送http请求带json格式数据
    a标签跳转,打开一个新页面
    echarts图例多行显示,并且全部对齐
    原子性,有序性,可见性
    winds消息大全
    C#中的结构体和对象区别
    装饰者模式
    hashMapp
    linux 定时任务
    windsServer2008设置定时重启
  • 原文地址:https://www.cnblogs.com/zrh-960906/p/11707606.html
Copyright © 2011-2022 走看看