zoukankan      html  css  js  c++  java
  • 序列化类Serializer 和 ModelSerializer 使用

    models.py

    from django.db import models
    
    # Create your models here.
    
    # 基表
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
        create_time = models.DateTimeField(auto_now_add=True, null=True)
    
        # abstract = true 表示基表为抽象表,不会完成数据库迁移
        class Meta:
            abstract = True
    
    
    class Book(BaseModel):
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        img = models.ImageField(upload_to='img', default='img/default.png')
        publish = models.ForeignKey(to='Publish', db_constraint=False,
                                    on_delete=models.DO_NOTHING, null=True)
        authors = models.ManyToManyField(to='Auth', db_constraint=False, null=True)
    
        class Meta:
            db_table = 'book'
            verbose_name = '书籍'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
        @property
        def publish_name(self):
            return self.publish.name
    
        @property
        def authors_info(self):
            authors_list =[]
            for author in self.authors.all():
                authors_list.append(
                    {'name':author.name,
                     'age':author.age,
                     'mobile':author.detail.mobile
                     }
                )
            return authors_list
    
    class Publish(BaseModel):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=64)
    
        class Meta:
            db_table = 'publish'
            verbose_name = '出版社'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class Auth(BaseModel):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        class Meta:
            db_table = 'auth'
            verbose_name = '作者'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class AuthDetail(BaseModel):
        mobile = models.CharField(max_length=11)
        author = models.OneToOneField(to='Auth',
                                      db_constraint=False,
                                      on_delete=models.CASCADE,
                                      null=True,
                                      related_name='detail')
    
        class Meta:
            db_table = 'auth_detail'
            verbose_name = '作者详情'
            verbose_name_plural = verbose_name
    
    
    class User(models.Model):
        SEX_CHOICE = [
            (0, '男'),
            (1, '女'),
            (2, '未知')
        ]
        username = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        sex = models.IntegerField(choices=SEX_CHOICE, default=0)
        icon = models.ImageField(upload_to='icon', default='/icon/default.png')
    
        class Meta:
            db_table = 'user'
            verbose_name = '用户'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.username
    
    

    序列化类

    from rest_framework import serializers
    from django.conf import settings
    from api import models
    
    
    # class UserSerializer(serializers.Serializer):
    #     username = serializers.CharField()
    #     # pwd = serializers.CharField()
    #     sex = serializers.IntegerField()
    #     icon = serializers.ImageField()
    
    
    class UserV2Serializer(serializers.Serializer):
        username = serializers.CharField(min_length=4,
                                         max_length=8,
                                         error_messages={
                                             'min_length': '用户名最少4位!',
                                             'max_length': '用户名最长8位!'
                                         }
                                         )
        pwd = serializers.CharField(write_only=True,
                                    min_length=6,
                                    max_length=10,
                                    error_messages={
                                        'min_length': '密码最少6位!',
                                        'max_length': '密码最长10位!'
                                    })
        re_pwd = serializers.CharField(min_length=6,
                                       max_length=10,
                                       write_only=True,
                                       required=True,
                                       error_messages={
                                           'min_length': '密码最少6位!',
                                           'max_length': '密码最长10位!',
                                           'required': '必须确认密码!'
                                       }
                                       )
        sex = serializers.IntegerField(write_only=True, required=False)
    
        gender = serializers.SerializerMethodField(read_only=True)
        def get_gender(self, user_obj):
            return user_obj.get_sex_display()
    
        icon = serializers.SerializerMethodField(read_only=True)
        def get_icon(self, user_obj):
            icon_url = 'http://127.0.0.1:8000{}{}'.format(settings.MEDIA_URL, user_obj.icon)
            return icon_url
    
        #局部校验
        def validate_username(self, value):
            if 'sb' in value:
                raise serializers.ValidationError('用户名包含敏感词汇!')
            return value
    
        def validate(self, attrs):
            pwd = attrs.get('pwd')
            re_pwd = attrs.get('re_pwd')
            if pwd:
                if re_pwd:
                    attrs.pop('re_pwd')
                    if pwd != re_pwd:
                        raise serializers.ValidationError('两次密码不一致!')
                else:
                    raise serializers.ValidationError('必须确认密码!')
            return attrs
        # 继承serializers.Serializer增加数据需要重写create方法,继承ModelSerializer不需要
        def create(self, validated_data):
            try:
                return models.User.objects.create(**validated_data)
            except:
                raise IOError('数据入库失败!')
    
    
    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 'price', 'publish_name', 'authors_info') # 表示只参与序列化的字段
            # exclude = ('id',)  # 表示不参与序列化的字段
    
    # 序列化与反序列化整合
    class BookModelSerializerV2(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 'price', 'publish', 'authors', 'img', 'publish_name', 'authors_info')
            extra_kwargs = {
                'publish': {
                    'required': True,
                    'write_only': True,
                    'error_messages': {
                        'required': 'publish必填!'
                    }
                },
                'authors': {
                    'required': True,
                    'write_only': True,
                    'error_messages': {
                        'required': 'authors必填!'
                    }
                },
                'img': {
                    'read_only': True
                }
            }
        #局部校验
        def validate_name(self, value):
            if 'sb' in value:
                raise serializers.ValidationError('书名包含敏感词汇!')
            return value
        # 全局校验
        def validate(self, attrs):
            name = attrs.get('name')
            publish = attrs.get('publish')
            if models.Book.objects.filter(name=name, publish=publish):
                raise serializers.ValidationError('书籍已经存在!')
            return attrs
    

    urls.py

    from django.urls import path, re_path
    from . import views
    
    urlpatterns = [
        # path('admin/', admin.site.urls),
        # path('books/', views.BookView.as_view()),
        # re_path('books/(?P<pk>.*)/', views.BookView.as_view()),
    
        path('users/', views.UserAPIView.as_view()),
        re_path('users/(?P<pk>.*)/', views.UserAPIView.as_view()),
    
        path('books/', views.BookModelAPIView.as_view()),
        re_path('books/(?P<pk>.*)/', views.BookModelAPIView.as_view()),
    
        # path('test/', views.my_view),
    ]
    

    views.py

    from django.shortcuts import render,HttpResponse
    from django.http import JsonResponse
    from django.views import View
    from . import models, myserializers
    
    from rest_framework.views import APIView
    from rest_framework.response import Response
    # Create your views here.
    
    
    class BookView(View):
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:
                book_info_list = models.Book.objects.filter(pk=pk).values('name', 'price')
                if not book_info_list:
                    return JsonResponse({
                        'status': 2,
                        'msg': '书籍不存在!'
                    })
                return JsonResponse({
                    'status': 1,
                    'msg': 'ok',
                    'result': book_info_list[0]
                })
            book_info_list = models.Book.objects.values('id', 'name', 'price')
            if not book_info_list:
                return JsonResponse({
                    'status': 2,
                    'msg': '没有数据!'
                })
            return JsonResponse({
                'status': 1,
                'msg': 'ok',
                'result': list(book_info_list)
            })
            # return JsonResponse({})
    
    
    class UserAPIView(APIView):
        def get(self, request, *args, **kwargs):
            user_query = models.User.objects.all()
            user_ser = myserializers.UserV2Serializer(user_query, many=True)
            # print(user_ser.data)
            return Response(data=user_ser.data)
    
    
        def post(self, request):
            request_data = request.data
            user_ser = myserializers.UserV2Serializer(data=request_data)
            if user_ser.is_valid():
                user_obj = user_ser.save()
                re_data = myserializers.UserV2Serializer(user_obj).data
                return Response(data=re_data)
            else:
                return Response(status=201,data=user_ser.errors)
    
    
    class BookModelAPIView(APIView):
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            print(pk)
            if pk:
                book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
                if not book_obj:
                    return Response('书籍不存在!')
                book_ser = myserializers.BookModelSerializerV2(book_obj)
                return Response(data=book_ser.data)
            book_query = models.Book.objects.filter(is_delete=False)
            book_ser = myserializers.BookModelSerializerV2(book_query, many=True)
            return Response(data=book_ser.data)
    
        def post(self, request, *args, **kwargs):
            request_data = request.data
            book_ser = myserializers.BookModelSerializerV2(data=request_data)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                res_data = myserializers.BookModelSerializerV2(book_obj).data
                return Response(data=res_data)
            else:
                return Response(data=book_ser.errors)
    
    
        def delete(self, request, *args, **kwargs):
            # 有名分组传参在kwargs中获取
            pk = kwargs.get('pk')
            print(pk)
            if pk:
                pks = [pk]
            else:
                pks = request.data.get('pks')
            if not pks:
                return Response('删除失败!')
            print(pks)
            book_query = models.Book.objects.filter(is_delete=False, pk__in=pks)
            res = book_query.update(is_delete=True)
            if not res:
                return Response('删除失败!')
            return Response('删除成功!')
    
    
    
  • 相关阅读:
    Java Runtime.exec()的使用
    加密备忘
    maven 配置 Java Servlet API
    flume spooldir bug修复
    修复eclipse build-helper-maven-plugin 异常
    Win10系统安装Office2016错误,提示需要更新客户端的解决方法
    ORA-14300: 分区关键字映射到超出允许的最大分区数的分区
    ORA-14402:更新分区关键字列将导致分区更改(分区表注意)
    oracle 11g自动时间分区备忘
    Oracle计算时间函数(numtodsinterval、numtoyminterval)
  • 原文地址:https://www.cnblogs.com/zhaogang0104/p/13025715.html
Copyright © 2011-2022 走看看