什么是序列化与反序列化

序列化

把模型对象转化成字典,经过 Respon 变成json字符串

反序列化

把客户端发送过来的数据,经过 request 变成字典,序列化器可以把字典转化成模型

序列化类Serializer使用

serializer.py

  1. from rest_framework import serializers
  2. from .models import Book
  3. class BookSerializer(serializers.Serializer):
  4. name = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
  5. price = serializers.IntegerField()
  6. publish = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
  7. author = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
  8. def create(self, validated_data):
  9. return Book.objects.create(**validated_data)
  10. def update(self, instance, validated_data):
  11. # instance.name = validated_data.get('name', instance.name)
  12. # instance.price = validated_data.get('price', instance.price)
  13. # instance.publish = validated_data.get('publish', instance.publish)
  14. # instance.author = validated_data.get('author', instance.author)
  15. for k, v in validated_data.items():
  16. setattr(instance, k, v)
  17. instance.save()
  18. return instance

views.py

  1. class BookAPIView(APIView):
  2. def get(self, request):
  3. books = Book.objects.all()
  4. ser = BookSerializer(instance=books, many=True)
  5. return Response(ser.data)
  6. def post(self, request):
  7. # data = request.data
  8. data = json.loads(request.body)
  9. ser = BookSerializer(data=data)
  10. # 校验数据是否合法
  11. if ser.is_valid():
  12. # 记得保存
  13. ser.save()
  14. return Response(ser.data)
  15. def put(self, request):
  16. # data = request.data
  17. data = json.loads(request.body)
  18. name = data.get('name')
  19. book = Book.objects.filter(name=name).first()
  20. ser = BookSerializer(book, data=data)
  21. if ser.is_valid():
  22. ser.save()
  23. return Response(ser.data)
  24. class BookDetailView(APIView):
  25. def get(self, request, cid):
  26. book = Book.objects.filter(pk=cid).first()
  27. ser = BookSerializer(instance=book)
  28. return Response(ser.data)
  29. def delete(self, request, cid):
  30. book = Book.objects.filter(pk=cid).first()
  31. if book:
  32. book.delete()
  33. ser = BookSerializer(instance=book)
  34. return Response(ser.data)

models.py

  1. class Book(models.Model):
  2. name = models.CharField(max_length=32)
  3. price = models.IntegerField()
  4. publish = models.CharField(max_length=32)
  5. author = models.CharField(max_length=32)

url

  1. from django.contrib import admin
  2. from django.urls import path
  3. from app01 import views
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('books/', views.BookAPIView.as_view()),
  7. path('books/<int:cid>/', views.BookDetailView.as_view()),
  8. path('index/', views.BookView.as_view()),
  9. ]

序列化字段类型和字段参数

字段类型

字段 字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None , min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
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"
IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

字段参数

参数 说明
max_length 最大长度
min_length 最小长度
max_value 最大值
min_value 最小值
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
read_only 表明该字段仅用于序列化输出,默认False
(只能查看,不能修改)
write_only 表明该字段仅用于反序列化输入,默认False
(只能修改,不能查看)
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None
,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
`help_text 用于HTML展示API页面时,显示的字段帮助提示信息

序列化器的字段校验功能

字段自带的校验规则

  1. class BookSerializer(serializers.Serializer):
  2. id = serializers.IntegerField(required=False)
  3. title = serializers.CharField(max_length=32)
  4. price = serializers.DecimalField(max_digits=6, decimal_places=2)
  5. publisher = serializers.CharField(max_length=32)

validators的校验

  1. # validators的校验,类似于局部钩子
  2. def check(data):
  3. if len(data) > 10:
  4. raise ValidationError('最长不能超过10')
  5. return data
  6. class BookSerializer(serializers.Serializer):
  7. id = serializers.IntegerField(required=False)
  8. title = serializers.CharField(max_length=32)
  9. price = serializers.DecimalField(max_digits=6, decimal_places=2)
  10. publisher = serializers.CharField(max_length=32, validators=[check, ]) # 在这里用:validators=[check, ],可以放在一个列表中

局部钩子与全局钩子

  1. # 局部钩子:validate_字段名
  2. def validate_age(self, age):
  3. if int(age) > 100:
  4. raise ValidationError('年龄不能大于100')
  5. return age
  6. # 全局钩子
  7. def validate(self, attrs):
  8. name = attrs.get('name')
  9. age = attrs.get('age')
  10. if age == name:
  11. raise ValidationError('年龄和名字不能相同')
  12. return attrs

序列化类ModelSerializer

  1. class BookSerializer(serializer.ModelSerializer):
  2. class Meta:
  3. model = 表模型 # 跟哪个表模型建立关系
  4. fields = ['字段1', '字段2'] # 序列化的字段,反序列化的字段
  5. fields = '__all__' # 所有字段都序列化,反序列化
  6. exclude=['字段1''字段2'] # 排除哪些字段(不能跟fields同时使用)
  7. read_only_fields=['price','publish'] # 序列化显示的字段
  8. write_only_fields=['title'] # 反序列化需要传入的字段
  9. extra_kwargs ={'title':{'max_length':32,'write_only':True}}
  10. depth=1 # 跨表查询1次,最多建议写3
  11. # 表示重写name这个字段,会走它的规则
  12. name = serializers.CharField(max_length=32min_length=3)

注意:

  • 局部全局钩跟之前没有任何区别
  • createupdate不需要写了(内部已经写好了)
  • 可以重写某个字段,注意缩进

多表序列化

方法名叫get_字段名,返回值就是要显示的东西

方式一

重写字段+必须配合一个方法,方法返回什么,该字段就是什么(该字段只能序列化)

  1. class BookSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Book
  4. fields = ['nid', 'name', 'price', 'publish_detail', 'author_detail', 'publish', 'authors']
  5. # depth = 1
  6. extra_kwargs = {
  7. 'publish': {'write_only': True},
  8. 'authors': {'write_only': True},
  9. }
  10. publish_detail = serializers.SerializerMethodField(read_only=True)
  11. def get_publish_detail(self, obj):
  12. return {'name': obj.name, 'city': obj.publish.city}
  13. author_detail = serializers.SerializerMethodField(read_only=True)
  14. def get_author_detail(self, obj):
  15. author_list = []
  16. for author in obj.authors.all():
  17. author_list.append({'name': author.name, 'addr': author.author_detail.addr})
  18. return author_list

方式二

在表模型models中写方法,在序列化类中写到fields