什么是序列化与反序列化
序列化
把模型对象转化成字典,经过 Respon 变成json字符串
反序列化
把客户端发送过来的数据,经过 request 变成字典,序列化器可以把字典转化成模型
序列化类Serializer使用
serializer.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
price = serializers.IntegerField()
publish = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
author = serializers.CharField(max_length=32, min_length=3, allow_blank=False, trim_whitespace=True)
def create(self, validated_data):
return Book.objects.create(**validated_data)
def update(self, instance, validated_data):
# instance.name = validated_data.get('name', instance.name)
# instance.price = validated_data.get('price', instance.price)
# instance.publish = validated_data.get('publish', instance.publish)
# instance.author = validated_data.get('author', instance.author)
for k, v in validated_data.items():
setattr(instance, k, v)
instance.save()
return instance
views.py
class BookAPIView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(self, request):
# data = request.data
data = json.loads(request.body)
ser = BookSerializer(data=data)
# 校验数据是否合法
if ser.is_valid():
# 记得保存
ser.save()
return Response(ser.data)
def put(self, request):
# data = request.data
data = json.loads(request.body)
name = data.get('name')
book = Book.objects.filter(name=name).first()
ser = BookSerializer(book, data=data)
if ser.is_valid():
ser.save()
return Response(ser.data)
class BookDetailView(APIView):
def get(self, request, cid):
book = Book.objects.filter(pk=cid).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
def delete(self, request, cid):
book = Book.objects.filter(pk=cid).first()
if book:
book.delete()
ser = BookSerializer(instance=book)
return Response(ser.data)
models.py
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
publish = models.CharField(max_length=32)
author = models.CharField(max_length=32)
url
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookAPIView.as_view()),
path('books/<int:cid>/', views.BookDetailView.as_view()),
path('index/', views.BookView.as_view()),
]
序列化字段类型和字段参数
字段类型
字段 | 字段构造方式 |
---|---|
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页面时,显示的字段帮助提示信息 |
序列化器的字段校验功能
字段自带的校验规则
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
title = serializers.CharField(max_length=32)
price = serializers.DecimalField(max_digits=6, decimal_places=2)
publisher = serializers.CharField(max_length=32)
validators的校验
# validators的校验,类似于局部钩子
def check(data):
if len(data) > 10:
raise ValidationError('最长不能超过10')
return data
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
title = serializers.CharField(max_length=32)
price = serializers.DecimalField(max_digits=6, decimal_places=2)
publisher = serializers.CharField(max_length=32, validators=[check, ]) # 在这里用:validators=[check, ],可以放在一个列表中
局部钩子与全局钩子
# 局部钩子:validate_字段名
def validate_age(self, age):
if int(age) > 100:
raise ValidationError('年龄不能大于100')
return age
# 全局钩子
def validate(self, attrs):
name = attrs.get('name')
age = attrs.get('age')
if age == name:
raise ValidationError('年龄和名字不能相同')
return attrs
序列化类ModelSerializer
class BookSerializer(serializer.ModelSerializer):
class Meta:
model = 表模型 # 跟哪个表模型建立关系
fields = ['字段1', '字段2'] # 序列化的字段,反序列化的字段
fields = '__all__' # 所有字段都序列化,反序列化
exclude=['字段1','字段2'] # 排除哪些字段(不能跟fields同时使用)
read_only_fields=['price','publish'] # 序列化显示的字段
write_only_fields=['title'] # 反序列化需要传入的字段
extra_kwargs ={'title':{'max_length':32,'write_only':True}}
depth=1 # 跨表查询1次,最多建议写3
# 表示重写name这个字段,会走它的规则
name = serializers.CharField(max_length=32,min_length=3)
注意:
- 局部全局钩跟之前没有任何区别
create
和update
不需要写了(内部已经写好了)- 可以重写某个字段,注意缩进
多表序列化
方法名叫get_字段名
,返回值就是要显示的东西
方式一
重写字段+必须配合一个方法,方法返回什么,该字段就是什么(该字段只能序列化)
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['nid', 'name', 'price', 'publish_detail', 'author_detail', 'publish', 'authors']
# depth = 1
extra_kwargs = {
'publish': {'write_only': True},
'authors': {'write_only': True},
}
publish_detail = serializers.SerializerMethodField(read_only=True)
def get_publish_detail(self, obj):
return {'name': obj.name, 'city': obj.publish.city}
author_detail = serializers.SerializerMethodField(read_only=True)
def get_author_detail(self, obj):
author_list = []
for author in obj.authors.all():
author_list.append({'name': author.name, 'addr': author.author_detail.addr})
return author_list
方式二
在表模型models
中写方法,在序列化类中写到fields
中