drf04

今日内容概要

  • 序列化类和常用字段参数
  • 序列化高级用法之source
  • 序列化高级用法之定制字段的两种方式
  • 多表关联反序列化保存
  • 反序列化字段校验其他
  • ModelSerializer使用

序列化类和常用字段参数

1 BooleanField	      BooleanField()

2 NullBooleanField	  NullBooleanField()

3 CharField	CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)

4 EmailField	EmailField(max_length=None, min_length=None, allow_blank=False)

5 RegexField	RegexField(regex, max_length=None, min_length=None, allow_blank=False)

6 SlugField	SlugField(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+

7 URLField	URLField(max_length=200, min_length=None, allow_blank=False)

8 UUIDField	UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"

9 IPAddressField	IPAddressField(protocol=’both’, unpack_ipv4=False, **options)

10 IntegerField	IntegerField(max_value=None, min_value=None)

11 FloatField	FloatField(max_value=None, min_value=None)

12 DecimalField	DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置

13 DateTimeField	DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)

14 DateField	DateField(format=api_settings.DATE_FORMAT, input_formats=None)

15 TimeField	TimeField(format=api_settings.TIME_FORMAT, input_formats=None)

16 DurationField	DurationField()

17 ChoiceField	ChoiceField(choices) choices与Django的用法相同

18 MultipleChoiceField	MultipleChoiceField(choices)

19 FileField	FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

20 ImageField	ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

ListField   ListFiel(child=, min_length=None, max_length=None)
DictField  DictField(child=)

#记住的: CharField	IntegerField  DecimalField
#	DateTimeField  BooleanField  ListField 
#  DictField

字段常用参数

  1. CharField及其子类的----反序列化的校验,字段自己的规则

    max_length		最大长度
    min_length		最短长度
    allow_blank		是否允许为空
    trim_whitespace	 是否截断空白字符
    
  2. IntegerField

    max_value		最小值
    min_value		最大值
    
  3. 所有的字段类都有的

    required 表明该字段在反序列化时必须输入,默认 是True

    default 反序列化时使用的默认值

    allow_null 表明该字段是否允许传入None,默认 False

    validatirs 该字段使用的验证器


    error_messages 包含错误编号与错误信息的字 典

    label 用于HTML招式API页面时,显示的字 段名称

    help_text 用于HTML展示API页面,显示的字段 帮助提示

重点

read_only 表明该字段仅用与序列化输出,默认 False

write_only 表明该字段仅用于反序列化输入,默认 False

反序列化校验执行流程

  1. 先执行字段自己的校验规则---》最大长度,最小长度,是否为空,是否必填,最小数字。。。

  2. validataor = [方法, ] -----》单独给这个字段加校验规则

    name = serializers.CharField(validators=[方法,])

  3. 局部钩子校验规则

  4. 全局钩子校验规则

序列化高级用法之source

准备操作

models层

from django.db import models


# Create your models here.



class Books(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    price = models.CharField(max_length=12, verbose_name="价格")
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')


class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    addr = models.CharField(max_length=32, verbose_name="地址")


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    phone = models.CharField(max_length=11, verbose_name={"手机号"})
    detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)


class AuthorDetail(models.Model):
    gender_choice = (
        (1, '男'),
        (2, '女'),
        (3, '其他')
    )
    gender = models.IntegerField(choices=gender_choice, verbose_name='性别')

view层

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from .serializer import BookSerializer
from .models import Books
from rest_framework.response import Response


class BooksView(APIView):

    def get(self, reqeust):
        book_query_set = Books.objects.all()
        res = BookSerializer(instance=book_query_set, many=True)
        return Response(res.data)

url层

path('books/', views.BooksView.as_view()),

定制名字

serializer层

class BookSerializer(serializers.Serializer):
    name_real = serializers.CharField(min_length=1, max_length=8, source='name')
    price_real = serializers.CharField(min_length=1, source='price')

serializer层

class BookSerializer(serializers.Serializer):
    # source 可以指定序列化字段的名字
    # 自有字段直接写字段的名字
    name_real = serializers.CharField(min_length=1, max_length=8, source='name')
    price_real = serializers.CharField(min_length=1, source='price')
    # 定义返回格式 返回单个数据可以用 source
    # 关联字段, 一对多的关联直接点
    publish = serializers.CharField(source='publish.name')
    # 多对多的搞不了
    # 返回多个
    authors = serializers.CharField(source='authors.all')

但是返回的有多个数据就不行了

序列化高级用法之定义字段的两种方式

定制关联字段的显示形式

  • 一对多显示字典
  • 多对多显示列表套字典

方式一 SerializerMethodField定制

class BookSerializer(serializers.Serializer):
    name_real = serializers.CharField(min_length=1, max_length=8, source='name')
    price_real = serializers.CharField(min_length=1, source='price')

    # 定制返回格式  方式一
    publish_detail = serializers.SerializerMethodField()

    def get_publish_detail(self, obj):
        return {"name": obj.publish.name, "addr": obj.publish.addr}

    authors = serializers.SerializerMethodField()

    def get_authors(self, obj):
        l = []
        for author_obj in obj.authors.all():
            l.append(
                {"name": author_obj.name, "phone": author_obj.phone, "gender": author_obj.detail.get_gender_display()})
        return l

方式二 在模型表中定制

model层

class Books(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    price = models.CharField(max_length=12, verbose_name="价格")
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    @property  # 可以加也可以不加
    def publish_detail(self):
        return {"name": self.publish.name, "addr": self.publish.addr}

    @property  # 可以加也可以不加
    def authors_list(self):
        l = []
        for author_obj in self.authors.all():
            l.append({"name": author_obj.name, "phone": author_obj.phone,
                      "gender": author_obj.detail.get_gender_display()})
        return l

serializer层

class BookSerializer(serializers.Serializer):
    name_real = serializers.CharField(min_length=1, max_length=8, source='name')
    price_real = serializers.CharField(min_length=1, source='price')

    # 定制返回格式  方式二 在模型类中定制
    publish_detail = serializers.DictField()

    authors_list = serializers.ListField()

多表关联反序列化保存

新增图书

serializer层

from .models import Books, Publish, Author, AuthorDetail


class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()
    # 定制返回格式  方式二 在模型类中定制
    publish_detail = serializers.DictField(read_only=True)
    authors_list = serializers.ListField(read_only=True)
    publish_id = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)

    def create(self, validated_data):
        print(validated_data)
        # 传过来的数据 {name: "三国演义", price: 33, publish_id: 1, authors: [1, 2]}
        authors = validated_data.pop("authors")
        book_obj = Books.objects.create(**validated_data)
        book_obj.authors.add(*authors)
        return book_obj

添加

修改

serializer层

from .models import Books, Publish, Author, AuthorDetail


class BookSerializer(serializers.Serializer):
    book_obj = Books()
    book_field = [field for field in book_obj.__dict__ if not field.startswith("_")]
    name = serializers.CharField(max_length=8)
    price = serializers.CharField()
    # 定制返回格式  方式二 在模型类中定制
    publish_detail = serializers.DictField(read_only=True)
    authors_list = serializers.ListField(read_only=True)
    publish_id = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)


def update(self, instance, validated_data):
        self.book_field.remove("id")
        authors_list = validated_data.pop('authors')
        for field in self.book_field:
            setattr(instance, field, validated_data.get(field))
        instance.authors.clear()
        instance.authors.add(*authors_list)
        instance.save()
        return instance

反序列化字段校验

  1. 字段自己的:举例

  1. validators = [方法, ] 忽略掉

  2. 局部钩子

  3. 全局钩子

字段自己的:举例 ----》validators ----》局部钩子----》全局钩子

ModelSerializer使用

ModelSerializer 继承自己Serializer,帮咱们完成了很多操作

  • 跟表模型强关联
  • 大部分请求,不用写create和update了
class BookSerializer(serializers.ModelSerializer):
    # 跟表有关系
    class Meta:
        model = Books  # 跟book表建立了关系 序列化类和表模型类
        fields = '__all__'  # 序列化所有的Books表里面的字段

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关系
    class Meta:
        model = Books  # 跟book表建立了关系 序列化类和表模型类
        # fields = '__all__'  # 序列化所有的Books表里面的字段
        # 序列化部分字段
        fields = ['name', 'price']

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关系
    class Meta:
        model = Books  # 跟book表建立了关系 序列化类和表模型类
        # fields = '__all__'  # 序列化所有的Books表里面的字段
        # 序列化部分字段
        fields = ['name', 'price', "publish_detail", "authors_list",
                  "publish", "authors"]
        # 定制name反序列化时: 最长不能超过8, 给字段类加属性
        # 方式一 定制 字段
        extra_kwargs = {"name": {"max_length": 8},
                        "publish_detail": {'read_only': True},
                        "authors_list": {'read_only': True},
                        "publish": {'write_only': True},
                        "authors": {'write_only': True},
                        }

跟原来的一样

class BookSerializer(serializers.ModelSerializer):
    # 跟表有关系
    class Meta:
        model = Books  # 跟book表建立了关系 序列化类和表模型类
        # fields = '__all__'  # 序列化所有的Books表里面的字段
        # 序列化部分字段
        fields = ['name', 'price', "publish_detail", "authors_list",
                  "publish", "authors"]
        # 定制name反序列化时: 最长不能超过8, 给字段类加属性             

        # 方式二 重写这些字段
        name = serializers.CharField(max_length=8)
        # 同理所有的read_only和wir_only都可以通过重写或使用
        # extra_kwargs传入
        # 你写了就先用你自己写的

        publish_detail = serializers.SerializerMethodField(read_only=True)

        def get_publish_detail(self, obj):
            return {"name": obj.publish.name, "addr": obj.publish.addr}

        author_list = serializers.SerializerMethodField(read_only=True)

        def get_author_list(self, obj):
            l = []
            for author_obj in obj.authos.all():
                l.append({"name": author_obj.name, "phone": author_obj.phoen,
                          "gender": author_obj.detail.get_gender_display()})
            return l

        # 局部钩子
        def validate_name(self, name):
            if name.startswith('sb'):
                raise ValidationError('不能sb')

            else:
                return name

作业

model层

from django.db import models


# Create your models here.


class Books(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    price = models.CharField(max_length=12, verbose_name="价格")
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    @property  # 可以加也可以不加
    def publish_detail(self):
        return {"name": self.publish.name, "addr": self.publish.addr}

    @property  # 可以加也可以不加
    def authors_list(self):
        l = []
        for author_obj in self.authors.all():
            l.append({"name": author_obj.name, "phone": author_obj.phone,
                      "gender": author_obj.detail.get_gender_display()})
        return l


class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    addr = models.CharField(max_length=32, verbose_name="地址")


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="用户名")
    phone = models.CharField(max_length=11, verbose_name={"手机号"})
    detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)


class AuthorDetail(models.Model):
    gender_choice = (
        (1, '男'),
        (2, '女'),
        (3, '其他')
    )
    gender = models.IntegerField(choices=gender_choice, verbose_name='性别')

serializer层

from .models import Books, Publish, Author, AuthorDetail
from rest_framework.exceptions import ValidationError


#
# def func1(price):
#     if int(price) > 80:
#         raise ValidationError("太贵了")
#
#
# class BookSerializer(serializers.Serializer):
#     book_obj = Books()
#     book_field = [field for field in book_obj.__dict__ if not field.startswith("_")]
#     name = serializers.CharField(max_length=8, error_messages={"max_length": "名字太长了"})
#     price = serializers.CharField(validators=[func1, ])
#
#     # 定制返回格式  方式二 在模型类中定制
#     publish_detail = serializers.DictField(read_only=True)
#     authors_list = serializers.ListField(read_only=True)
#     publish_id = serializers.CharField(write_only=True)
#     authors = serializers.ListField(write_only=True)
#
#     def create(self, validated_data):
#         # 传过来的数据 {name: "三国演义", price: 33, publish_id: 1, authors: [1, 2]}
#         authors = validated_data.pop("authors")
#         book_obj = Books.objects.create(**validated_data)
#         book_obj.authors.add(*authors)
#         return book_obj
#
#     def update(self, instance, validated_data):
#         self.book_field.remove("id")
#         authors_list = validated_data.pop('authors')
#         for field in self.book_field:
#             setattr(instance, field, validated_data.get(field))
#         instance.authors.clear()
#         instance.authors.add(*authors_list)
#         instance.save()
#         return instance

view层

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from .serializer import BookSerializer
from .models import Books
from rest_framework.response import Response


class BooksView(APIView):

    def get(self, reqeust):
        book_query_set = Books.objects.all()
        res = BookSerializer(instance=book_query_set, many=True)
        return Response(res.data)

    def post(self, reqeust):
        res = BookSerializer(data=reqeust.data)
        print(reqeust.data)
        if res.is_valid():
            res.save()
            return Response({"code": 100, "msg": "添加成功", "res": res.data})
        else:
            return Response({"code": 101, "msg": "添加失败", "error": res.errors})


class Books2View(APIView):
    def put(self, request, pk):
        book_obj = Books.objects.filter(pk=pk).first()
        res = BookSerializer(data=request.data, instance=book_obj)
        if res.is_valid():
            res.save()
            return Response({"code": 100, "msg": "修改成功", "res": res.data})
        else:
            return Response({"code": 101, "msg": "修改失败", "error": res.errors})
posted @ 2023-02-02 22:10  可否  阅读(52)  评论(0)    收藏  举报