序列化类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('删除成功!')


原文地址:https://www.cnblogs.com/zhaogang0104/p/13025715.html