pip install djangorestframework
INSTALLED_APPS = [
...
'rest_framework',
]
models.py
from django.db import models
''' 测试数据 仅供参考
INSERT INTO `demo_app_author` VALUES (1, '令狐冲', 25, 1);
INSERT INTO `demo_app_author` VALUES (2, '任我行', 58, 2);
INSERT INTO `demo_app_author` VALUES (3, '任盈盈', 23, 3);
INSERT INTO `demo_app_author` VALUES (4, '扫地僧', 99, 4);
INSERT INTO `demo_app_author` VALUES (5, '乔峰', 99, 5);
INSERT INTO `demo_app_authordetail` VALUES (1, 1, '13432335433', '华山', '1994-05-23');
INSERT INTO `demo_app_authordetail` VALUES (2, 1, '13943454554', '黑木崖', '1961-08-13');
INSERT INTO `demo_app_authordetail` VALUES (3, 0, '13878934322', '黑木崖', '1996-05-20');
INSERT INTO `demo_app_authordetail` VALUES (4, 0, '13878938322', '少林', '1996-05-20');
INSERT INTO `demo_app_authordetail` VALUES (5, 0, '13878939322', '大宋', '1996-05-20');
INSERT INTO `demo_app_book` VALUES (1, '笑傲江湖', 33.30, '2023-11-11', 1);
INSERT INTO `demo_app_book` VALUES (2, '天龙八部', 33.30, '2023-11-11', 1);
INSERT INTO `demo_app_book_authors` VALUES (1, 1, 1);
INSERT INTO `demo_app_book_authors` VALUES (2, 1, 2);
INSERT INTO `demo_app_book_authors` VALUES (3, 2, 1);
INSERT INTO `demo_app_book_authors` VALUES (4, 2, 2);
INSERT INTO `demo_app_publish` VALUES (1, '华山出版社', '华山', '[email protected]');
INSERT INTO `demo_app_publish` VALUES (2, '明教出版社', '黑木崖', '[email protected]');
INSERT INTO `demo_app_publish` VALUES (2, '萧峰版社', '大宋', '[email protected]');
'''
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField()
publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
authors = models.ManyToManyField("Author")
class Meta:
verbose_name = '书籍表'
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=64)
email = models.EmailField()
class Meta:
verbose_name = '出版社表'
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.SmallIntegerField()
au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)
class Meta:
verbose_name = '作者表'
class AuthorDetail(models.Model):
gender_choices = (
(0, "女"),
(1, "男"),
(2, "保密"),
)
gender = models.SmallIntegerField(choices=gender_choices)
tel = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
birthday = models.DateField()
class Meta:
verbose_name = '作者详情表'
urls.py
urlpatterns = [
path('books/',BookListView.as_view()),# 列表视图
path('books//' ,BookDataView.as_view()),# 详情视图
]
vuew.py
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.utils.html import escape
# Create your views here.
'''
GET /books/ 提供所有数据
POST /books/ 增加一条数据
GET /books// 提供指定id的记录
PUT /books// 修改指定ID的记录
DELETE /books// 删除指定id的记录
'''
from django.views import View
from .models import *
class BookListView(View):
'''
列表视图
'''
def get(self,request):
'''查询所有数据'''
# 1、查询出所有图书模型
book_list = Book.objects.filter().order_by('id')
# 2、遍历出里面的每个数据模型对象,把模型对象转换成json对象
data_list = []
for book in book_list:
book_dict = {
'id':book.id,
'title':book.title,
'price':book.price,
'pub_date':book.pub_date,
'publish':{
'id':book.publish.id,
'name':book.publish.name,
'city':book.publish.city,
'email':book.publish.email,
},
}
# 多堆对多
authors_list = book.authors.filter()
authors_data_list = []
for authors in authors_list:
authors_dict = {
'id': authors.id,
'name': authors.name,
'age': authors.age,
'gender': authors.au_detail.gender,
'tel': authors.au_detail.tel,
'addr': authors.au_detail.addr,
}
authors_data_list.append(authors_dict)
book_dict['authors'] = authors_data_list
data_list.append(book_dict)
# 3、响应
return JsonResponse(data_list,safe=False)
def post(self,request):
title = escape(request.POST.get('title',''))
price = escape(request.POST.get('price',''))
pub_date = escape(request.POST.get('pub_date',''))
publish_id = escape(request.POST.get('publish_id',''))
publish = Publish.objects.filter(pk=int(publish_id)).first()
book = Book(
title = title,
price = price,
pub_date = pub_date,
publish = publish
)
book.save()
# 新增关联
authors = Author.objects.filter(pk__in=[1, 2])
book.authors.add(*authors)
book_dict = {
'id': book.id,
'title': book.title,
'price': book.price,
'pub_date': book.pub_date,
'publish': {
'id': book.publish.id,
'name': book.publish.name,
'city': book.publish.city,
'email': book.publish.email,
},
}
authors_list = book.authors.filter()
authors_data_list = []
for authors in authors_list:
authors_dict = {
'id': authors.id,
'name': authors.name,
'age': authors.age,
'gender': authors.au_detail.gender,
'tel': authors.au_detail.tel,
'addr': authors.au_detail.addr,
}
authors_data_list.append(authors_dict)
book_dict['authors'] = authors_data_list
return JsonResponse(book_dict)
class BookDataView(View):
''' 详情视图 '''
def get(self,request,id):
''' 指定某个 图书接口'''
# 1、获取出指定id的那个模型对象
book = Book.objects.filter(pk=id).first()
# 2、模型对象字典
if not book:
return JsonResponse({'msg':"未查询到数据"})
book_dict = {
'id': book.id,
'title': book.title,
'price': book.price,
'pub_date': book.pub_date,
'publish': {
'id': book.publish.id,
'name': book.publish.name,
'city': book.publish.city,
'email': book.publish.email,
},
}
authors_list = book.authors.filter()
authors_data_list = []
for authors in authors_list:
authors_dict = {
'id': authors.id,
'name': authors.name,
'age': authors.age,
'gender': authors.au_detail.gender,
'tel': authors.au_detail.tel,
'addr': authors.au_detail.addr,
}
authors_data_list.append(authors_dict)
book_dict['authors'] = authors_data_list
# 3、响应
return JsonResponse(book_dict)
def put(self,request,id):
''' 修改 '''
# 1、先获取前端传入的新数据
# 2、将后端传入的数据就行赋值
book_obj = Book.objects.filter(pk=id).first()
if not book_obj:
return JsonResponse({'msg':"未查询到信息"})
title = escape(request.POST.get('title', ''))
price = escape(request.POST.get('price', ''))
pub_date = escape(request.POST.get('pub_date', ''))
publish_id = escape(request.POST.get('publish_id', ''))
if title:
book_obj.title = title
if price:
book_obj.price = price
if pub_date:
book_obj.pub_date = pub_date
if publish_id:
publish = Publish.objects.filter(pk=int(publish_id)).first()
book_obj.publish = publish
book_obj.save()
# 3、返回
book_dict = {
'id': book_obj.id,
'title': book_obj.title,
'price': book_obj.price,
'pub_date': book_obj.pub_date,
'publish': {
'id': book_obj.publish.id,
'name': book_obj.publish.name,
'city': book_obj.publish.city,
'email': book_obj.publish.email,
},
}
authors_list = book_obj.authors.filter()
authors_data_list = []
for authors in authors_list:
authors_dict = {
'id': authors.id,
'name': authors.name,
'age': authors.age,
'gender': authors.au_detail.gender,
'tel': authors.au_detail.tel,
'addr': authors.au_detail.addr,
}
authors_data_list.append(authors_dict)
book_dict['authors'] = authors_data_list
return JsonResponse(book_dict)
def delete(self,request,id):
''' 删除 '''
delete = Book.objects.filter(pk=id).delete()
return JsonResponse({'msg':"删除成功"})
urls.py
from rest_framework.routers import DefaultRouter
from django.urls import path
from .views import *
import rest_fromwork_views
urlpatterns = []
router = DefaultRouter()# 创建路由器
router.register(r'book',rest_fromwork_views.BookView)# 注册路由
urlpatterns += router.urls# 把生成好的路由拼接到urlpatterns中去
views.py
'''
GET /book/ 提供所有数据
POST /book/ 增加一条数据
GET /book// 提供指定id的记录
PUT /book// 修改指定ID的记录
DELETE /book// 删除指定id的记录
'''
from rest_framework.viewsets import ModelViewSet
from .models import *
from .serializers import *
class BookViews(ModelViewSet):
''' 定义类视图 '''
# 1、指定查询集 queryset
queryset = Book.objects.filter()
# 2、指定序列化器 serializer_class
serializer_class = BookSerializer
serializers.py
from rest_framework import serializers
from .models import Book, Publish, Author
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
class Meta:
model = Book
fields = '__all__'
序列化(输出、read_only)和反序列化(输入、write_only)
判断用户发送的数据是否合法(is_valid(raise_exception=True))
from rest_framework import serializers
from .models import Book, Publish, Author
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
class Meta:
model = Book
fields = '__all__'
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)# read_only=True只能做输出不能做输入;write_only=True:输入
title = serializers.CharField(label="标题",max_length=32,required=True)# required=True 必传,不写默认 True;只有当模型中 有默认值和允许为空才可以为 False
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_length | 最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 是否截断空白字符 |
max_value | 最小值 |
min_value | 最大值 |
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器 |
error_messages | 包含错误编号与错误的信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
required | 表明该字段的反序列化时必须虚入,默认值为True |
反序列化内容 中没有具体的 保存和修改方法,需要自己重写保存和修改方法。
from rest_framework import serializers
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,required=True)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
def create(self, validated_data):
'''
使用方法
NewPublishSerializer(data=data)
当调用序列化器的 save() 方法时,如果当初创建序列化器对象是没有 instance 传参数
:param validated_data: 得到的是 反序列化后的字段数据
:return:
'''
# 创建内容
publish = Publish.objects.create(**validated_data)
return publish
def update(self, instance, validated_data):
'''
使用方法:
NewPublishSerializer(instance=publish,data=data)
重写 update 方法 NewPublishSerializer(instance=publish,data=data)
如果创建序列化器时给 instance 传了参数,在调用序列化器的 save() 方法时实现时机会调用当前的 update
:param instance: 要修改的模型对象
:param validated_data:得到的是 反序列化后的字段数据
:return: 返回修改后的模型对象
'''
instance.name = validated_data.get('name')
instance.city = validated_data.get('city')
instance.email = validated_data.get('email')
instance.save()
return instance
from django.test import TestCase
from demo_app.serializers import *
data = {
'name':'武当山出版社',
'city':'武当山',
'email':'[email protected]',
}
serializer = NewPublishSerializer(data=data)
is_valid = serializer.is_valid()# 调用序列化的校验方法 True 或 False
print('校验是否通过is_valid:',is_valid)
errors = serializer.errors # 获取校验的错误信息
print('校验不通过内容原因errors:',errors)
#serializer.validated_data # 获取反序列化校验后的数据还是字段
print(serializer.validated_data)
publish = serializer.save()
from demo_app.serializers import *
data = {
'name':'武当山出版社',
'city':'武当山1111',
'email':'[email protected]',
}
publish_obj = Publish.objects.get(id=3)
# 调用
serializer = NewPublishSerializer(instance=publish_obj,data=data)
is_valid = serializer.is_valid(raise_exception=True)
publish = serializer.save()
调用序列化器的 .save() 方法,调用save 时会判断当初始创建序列化器时是否传入 instance ,如果传了 instance 也传了data 那么调用 save 实际调用序列化器中的 update() 方法反之就是调用序列化器中的 create 方法。
如果我们想要使用序列化器对应的是django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
ModelSerilizer与常规的Serializer 相同,但提供了:
创建BookSerializer
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()# 外键
authors = AuthorSerializer(many=True)# 多对多
class Meta:
model = Book
fields = '__all__'
通过 ModelSerializer 实现字段自动生成
只要一部分字段实现方法1 fields
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class AuthorDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AuthorDetail
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
class Meta:
model = Book
# fields = '__all__' # 全部字段
fields = ['id','title','publish','authors']# 只要list中的字段
只要一部分字段实现方法2 exclude
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class AuthorDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AuthorDetail
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
class Meta:
model = Book
# fields = '__all__' # 全部字段
# fields = ['id','title','publish','authors']# 只要list中的字段
exclude = ['pub_date'] #除了 pub_date 字段不映射 其他字段都要
其中自动生成的 字段中有些默认值会出现 问题例如 authors 中的 age字段 最小值是 -32768 在实际中最小值不可能小于0因此可以通过 extra_kwargs 来进行自定义限制
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
# 对 额外的字段进行修改
extra_kwargs = {
'age':{'min_value':0}# age 是对应字段名,min_value 对应的校验属性,都是以字典的形式
}
只对某些字段进行序列化
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
# 对 额外的字段进行修改
# extra_kwargs = {
# 'age':{'min_value':0}
# }
read_only_fields = ['age'] # 只对某些字段进行序列化
我们可以在python manage.py shell 中查看自动生成的 BookSerializer 的具体实现
我们可以在python manage.py shell 中查看自动生成的 BookSerializer 的具体实现
提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其他库自动和反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成API,满足各种需求;
多种身份认证和权限认证的支持;
内置限流系统;
只管的API web界面;
扩展性,插件丰富;
序列化器的作用:
1、进行数据的校验。
2、对数据对象进行转换。
在开发REST API 接口时,视图中的主要有三件事:
将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等)
for book in book_list:
book_dict = {
'id':book.id,
'title':book.title,
'price':book.price,
'pub_date':book.pub_date,
'publish':{
'id':book.publish.id,
'name':book.publish.name,
'city':book.publish.city,
'email':book.publish.email,
},
}
# 多对多
authors_list = book.authors.filter()
authors_data_list = []
for authors in authors_list:
authors_dict = {
'id': authors.id,
'name': authors.name,
'age': authors.age,
'gender': authors.au_detail.gender,
'tel': authors.au_detail.tel,
'addr': authors.au_detail.addr,
}
authors_data_list.append(authors_dict)
book_dict['authors'] = authors_data_list
data_list.append(book_dict)
# 3、响应
return JsonResponse(data_list,safe=False)
当前端需给前端响应模型数据时,需要将模型数据序列化成前端需要的格式。
在序列化器中有两个属性 instance 和 data;
instance参数: 模型、查询集、字典
#如果只给 instance 形参传递参数表示做序列化
serializer = BookSerializer(instance=book)
serializer.data # 就可以获取序列化后的数据
测试一
tests.py
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
datas = Book.objects.filter()
print("查询出的数据内容有多少条:",datas.count())
serializer = NewBookSerializer(instance=datas,many=True)# many=True:表示有多条数据,当只有一条数据的时候就不用many=False;默认many=False
print(serializer.data)
# 执行上述代码使用
'''
python manage.py test
'''
测试二
在序列化器中多增加一列
'''serializers.py'''
from rest_framework import serializers
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
publish = PublishSerializer()
authors = AuthorSerializer(many=True)
helle = serializers.CharField()# 多余字段
'''tests.py'''
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
data = Book.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewBookSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
'''
python manage.py test
'''
主要字段 serializers.PrimaryKeyRelatedField
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
# read_only = True :只做序列化
# queryset=Publish.objects.all() 当输入查询时不是Publish这里面的数据就会 报错
# PrimaryKeyRelatedField 外键关联
publish = serializers.PrimaryKeyRelatedField(label="出版社",read_only=True,queryset=Publish.objects.all())
from demo_app.serializers import *
from demo_app.models import *
data = Book.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewBookSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
**注意:**默认是将 关联的id查询出来。
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
# read_only = True :只做序列化
# queryset=Publish.objects.all() 当输入查询时不是Publish这里面的数据就会 报错
# PrimaryKeyRelatedField 外键关联
publish = serializers.StringRelatedField(label="出版社",read_only=True)
# publish = PublishSerializer()
# authors = AuthorSerializer(many=True)
# helle = serializers.CharField()# 多余字段
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
data = Book.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewBookSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
**注意:**返回值是 对象 obje (*) 的字符串
将关联模型对象的序列化器中所有字段序列化出来
from rest_framework import serializers
from .models import Book, Publish, Author
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
# read_only = True :只做序列化
# queryset=Publish.objects.all() 当输入查询时不是Publish这里面的数据就会 报错
# PrimaryKeyRelatedField 外键关联
# publish = serializers.StringRelatedField(label="出版社",read_only=True)
publish = PublishSerializer()
# authors = AuthorSerializer(many=True)
# helle = serializers.CharField()# 多余字段
出版社反向获取 书籍;
# coding=utf-8
'''
@date:2023/11/15 11:48
@mail:[email protected]
@Content: 序列化器
'''
from rest_framework import serializers
from .models import Book, Publish, Author
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
# publish = PublishSerializer()
# authors = AuthorSerializer(many=True)
# helle = serializers.CharField()# 多余字段
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,required=True)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
book_set = NewBookSerializer(many=True) # 注意
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
data = Publish.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewPublishSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
**注意:**使用 modesel名小写 + _set
# coding=utf-8
'''
@date:2023/11/15 11:48
@mail:[email protected]
@Content: 序列化
'''
from rest_framework import serializers
from .models import Book, Publish, Author
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = '__all__'
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
publish = PublishSerializer()
authors = AuthorSerializer(many=True)# 注意多对多 时 many=True
# helle = serializers.CharField()# 多余字段
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
data = Book.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewBookSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
# coding=utf-8
'''
@date:2023/11/15 11:48
@mail:[email protected]
@Content: 序列化器
'''
from rest_framework import serializers
from .models import Book, Publish, Author,AuthorDetail
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
class AuthorDetailSerializer(serializers.ModelSerializer):
class Meta:
model = AuthorDetail
fields = '__all__'
class NewBookSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id",read_only=True)
title = serializers.CharField(label="标题",max_length=32)
price = serializers.DecimalField(label="价格",max_digits=5,decimal_places=2)
pub_date = serializers.DateField()
# publish = PublishSerializer()
# authors = AuthorSerializer(many=True)
# helle = serializers.CharField()# 多余字段
class NewAuthSerializer(serializers.Serializer):
id = serializers.IntegerField(label="id", read_only=True)
name = serializers.CharField(label="姓名",max_length=32)
age = serializers.CharField(label="年龄",max_length=32)
au_detail = AuthorDetailSerializer()
book_set = NewBookSerializer(many=True)
from django.test import TestCase
# Create your tests here.
from demo_app.serializers import *
from demo_app.models import *
data = Author.objects.get(id=1)
data.helle = "测试多增加字段内容"
# print("查询出的数据内容有多少条:",data.count())
serializer = NewAuthSerializer(instance=data)# many=True:表示有多条数据,当只有一条数据的时候就不用many
print(serializer.data)
注意: 反向序列化使用 模型名+_set 即可
拿到前端传入的数据 —》 序列化器的data --》 调用序列化器的 .is_valid() 方法进行校验 —》 调用序列化器的 .save() 方法。
将其他格式(字典、JSON、XML等)转换为程序中的数据,例如JSON字符串转换为django中的模型类对象。
title = escape(request.POST.get('title',''))
price = escape(request.POST.get('price',''))
pub_date = escape(request.POST.get('pub_date',''))
publish_id = escape(request.POST.get('publish_id',''))
publish = Publish.objects.filter(pk=int(publish_id)).first()
book = Book(
title = title,
price = price,
pub_date = pub_date,
publish = publish
)
当需要将用户发送的数据存储到数据库之前,需要使用反序列化。
在序列化器中有两个属性 instance 和 data;
#如果只给 instance 形参传递参数表示做序列化
serializer = BookSerializer(data=jsondata)
serializer.data # 就可以获取反序列化数据
反序列化 = 前端发送的数据 —》 经过验证 --》python字典 —》 save --》 模型对象
**案例使用 Serializer **
反序列化内容 中没有具体的 保存和修改方法,需要自己重写保存和修改方法。
from rest_framework import serializers
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,required=True)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
def create(self, validated_data):
'''
使用方法
NewPublishSerializer(data=data)
当调用序列化器的 save() 方法时,如果当初创建序列化器对象是没有 instance 传参数
:param validated_data: 得到的是 反序列化后的字段数据
:return:
'''
# 创建内容
publish = Publish.objects.create(**validated_data)
return publish
def update(self, instance, validated_data):
'''
使用方法:
NewPublishSerializer(instance=publish,data=data)
重写 update 方法 NewPublishSerializer(instance=publish,data=data)
如果创建序列化器时给 instance 传了参数,在调用序列化器的 save() 方法时实现时机会调用当前的 update
:param instance: 要修改的模型对象
:param validated_data:得到的是 反序列化后的字段数据
:return: 返回修改后的模型对象
'''
instance.name = validated_data.get('name')
instance.city = validated_data.get('city')
instance.email = validated_data.get('email')
instance.save()
return instance
新增
from django.test import TestCase
from demo_app.serializers import *
data = {
'name':'武当山出版社',
'city':'武当山',
'email':'[email protected]',
}
serializer = NewPublishSerializer(data=data)
is_valid = serializer.is_valid()# 调用序列化的校验方法 True 或 False
print('校验是否通过is_valid:',is_valid)
errors = serializer.errors # 获取校验的错误信息
print('校验不通过内容原因errors:',errors)
#serializer.validated_data # 获取反序列化校验后的数据还是字段
print(serializer.validated_data)
publish = serializer.save()
修改方法
from demo_app.serializers import *
data = {
'name':'武当山出版社',
'city':'武当山1111',
'email':'[email protected]',
}
publish_obj = Publish.objects.get(id=3)
# 调用
serializer = NewPublishSerializer(instance=publish_obj,data=data)
is_valid = serializer.is_valid(raise_exception=True)
publish = serializer.save()
调用序列化器的 .save() 方法,调用save 时会判断当初始创建序列化器时是否传入 instance ,如果传了 instance 也传了data 那么调用 save 实际调用序列化器中的 update() 方法反之就是调用序列化器中的 create 方法。
在获取反序列化的数据前,必须调用 is_valid() 方法进行验证,验证成功返回True,否则返回False
验证失败,可以通过序列化器对象的error属性获取错误学习,返回字典,包含了字段和字 段的错误。
验证成功,可以通过序列化器对象的 validated_data 属性获取数据。
# 可以通过序列化器 进行context 进行传输数据
publish = NewPublishSerializer(instance=None,data=data,context={'request':request})
# 获取context 中的数据
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,
required=True,validators=[custom_fun1,custom_fun2]
)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
def create(self, validated_data):
'''
当调用序列化器的 save() 方法时,如果当初创建序列化器对象是没有 instance 传参数
:param validated_data: 得到的是 反序列化后的字段数据
:return:
'''
# 创建内容
publish = Publish.objects.create(**validated_data)
return publish
def update(self, instance, validated_data):
'''
重写 update 方法
如果创建序列化器时给 instance 传了参数,在调用序列化器的 save() 方法时实现时机会调用当前的 update
:param instance: 要修改的模型对象
:param validated_data:得到的是 反序列化后的字段数据
:return: 返回修改后的模型对象
'''
request = self.context['request']
instance.name = validated_data.get('name')
instance.city = validated_data.get('city')
instance.email = validated_data.get('email')
instance.save()
return instance
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,required=True)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
# 序列化器中单独增加校验逻辑
def validate_name(self,value):
'''
复杂校验内容数据 validate_+字段名称
:param value: 当前字段值
:return: 返回value
'''
if '出版社' not in value:
# 只要在序列化器中 抛出的异常都叫做 ValidationError 异常
raise serializers.ValidationError('名称中不包含 出版社等字')
return value # 将校验内容返回回去
测试代码
from demo_app.serializers import *
data = {
'name':'武当',
# 'city':'武当山',
'email':'[email protected]',
}
serializer = NewPublishSerializer(data=data)
is_valid = serializer.is_valid()# 调用序列化的校验方法 True 或 False
print('校验是否通过is_valid:',is_valid)
#is_valid2 = serializer.is_valid(raise_exception=True)# raise_exception=True 如果有异常会自动输出异常# 就不用在.error 获取异常
#print('校验是否通过is_valid2:',is_valid2)
errors = serializer.errors # 获取校验的错误信息
print('校验不通过内容原因errors:',errors)
serializer.validated_data # 获取反序列化校验后的数据还是字段
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,required=True)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
def validate(self,attrs):
'''
同时校验多个字段 联合校验
:param attrs: 里面是前端 传入过来的所有数据
:return: 返回数据
# 在联合校验中,可以对单个字段进行校验也可以对多个字段进行校验
# 也可以对在传入的字段中增加 一个属性
'''
name = attrs['name']
print(attrs)
if '出版社' not in name:
# 只要在序列化器中 抛出的异常都叫做 ValidationError 异常
raise serializers.ValidationError('名称中不包含 出版社等字')
return attrs
from demo_app.serializers import *
data = {
'name':'武当',
'city':'武当山',
'email':'[email protected]',
}
serializer = NewPublishSerializer(data=data)
is_valid = serializer.is_valid()# 调用序列化的校验方法 True 或 False
print('校验是否通过is_valid:',is_valid)
errors = serializer.errors # 获取校验的错误信息
print('校验不通过内容原因errors:',errors)
# serializer.validated_data # 获取反序列化校验后的数据还是字段
注意:
在字段中添加 validators 选项参数,可以补充验证行为;
**使用:**当多个字段存在相同的校验就可以使用自定义的方法校验。
def custom_fun1(value):
if '出版社' not in value:
# 只要在序列化器中 抛出的异常都叫做 ValidationError 异常
raise serializers.ValidationError('名称中不包含 出版社等字')
return value
def custom_fun2(value):
if 'python' in value:
# 只要在序列化器中 抛出的异常都叫做 ValidationError 异常
raise serializers.ValidationError('名称中不能包含 python')
return value
class NewPublishSerializer(serializers.Serializer):
id = serializers.IntegerField(label="ID",read_only=True)
name = serializers.CharField(label="出版社名称",max_length=32,
required=True,validators=[custom_fun1,custom_fun2]
)
city = serializers.CharField(label="城市",max_length=64,required=True)
email = serializers.EmailField(label="邮箱",required=True)
from django.test import TestCase
from demo_app.serializers import *
data = {
'name':'武当python',
'city':'武当山',
'email':'[email protected]',
}
serializer = NewPublishSerializer(data=data)
is_valid = serializer.is_valid()# 调用序列化的校验方法 True 或 False
print('校验是否通过is_valid:',is_valid)
errors = serializer.errors # 获取校验的错误信息
print('校验不通过内容原因errors:',errors)
# serializer.validated_data # 获取反序列化校验后的数据还是字段
在开发REST API接口时,我们在视图中需要做的最核心的事是: