3-3 序列化-DRF模型序列化高级
目录:
- 设计分类表(Category)(1对多)
- 序列化高级用法:
StringRelatedField:将返回一个对应的 model的str() 方法的字符串。 PrimaryKeyRelatedField: 将返回一个对应关系 model 的主键。 HyperlinkedRelatedField:使用 HyperlinkedRelatedField 将返回一个超链接,该链接指向对应关系 model 的详细数据,view-name 是必选参数,为对应的视图生成超链接。 SlugRelatedField:将返回一个指定对应关系 model 中的字段,需要参数 slug_field 中指定字段名称。 HyperlinkedIdentityField:将返回指定 view-name 的超链接的字段。
- HyperlinkedModelSerializer的使用
- 嵌套序列化关系模型
- 深度遍历:depth
- 自定义属性:SerializerMethodField
- 自定义数据源:source
- to_representation方法(多对多关系):自定义字段格式显示
一、设计分类表(Category)(1对多)
我们设计分类表(Category),与文章表(Article)是一对多的关系,然后我们通过这个关系,看下 序列化高级的用法。废话不多,我们先来设计表结构(1对多)
1.1、设计模型类
说明:分类表(Category) 和 文章表(Article) 是 一对多外键关系。在 models.py中 设计表结构:
from django.db import models
class Article(models.Model):
....
category = models.ForeignKey(to="Category",on_delete=models.CASCADE,related_name="articles") #related_name反查
def __str__(self):
return self.title
class Category(models.Model):
name = models.CharField(verbose_name="分类",max_length=10)
def __str__(self):
return self.name
1.2、序列化
说明:编写 serializers.py序列化文件,设置序列化。fields显示的字段,是你 返回的值显示的。
from rest_framework import serializers
from .models import Article,Category
#模型序列化
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category') #增加 category 序列化外键
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name')
1.3、设置路由
说明:这个在子路由中设置。上面我们已经设置过了父路由的设置。app02 -> urls.py
from django.urls import path
from app02 import views
urlpatterns = [
...
#新增 category的路由
path("category/", views.category_list, name="category-list"),
path("category/<int:id>/", views.category_detail, name="category-detail"),
]
1.4、视图
说明:编辑 views.py,增加 分类的(category) 视图代码,跟article是一样的逻辑。
from .serializers import ArticleSerializer,CategorySerializer .... from .models import Article,Category .... # Create your views here. class JSONResponse(HttpResponse): """重新封装一下HttpResponse避免重复代码""" ... @csrf_exempt def article_list(request): ... @csrf_exempt def article_detail(request,id): ... @csrf_exempt def category_list(request): """ 文章标题 :return: """ if request.method == "GET": arts = Category.objects.all() ser = CategorySerializer(instance=arts, many=True) return JSONResponse(ser.data, status=200) elif request.method == "POST": data = JSONParser().parse(request) ser = CategorySerializer(data=data) if ser.is_valid(): ser.save() return JSONResponse(ser.data, status=201) return JSONResponse(ser.errors,status=401) @csrf_exempt def category_detail(request,id): """ 文章详情 :param request: :param id: 文章id :return: """ try: art = Category.objects.get(id=id) except Category.DoesNotExist as e: return HttpResponse(status=404) if request.method == "GET": ser = CategorySerializer(instance=art) return JSONResponse(ser.data,status=200) elif request.method == "PUT": data = JSONParser().parse(request) ser = CategorySerializer(instance=art,data=data) if ser.is_valid(): ser.save() return JSONResponse(ser.data,status=201) return JSONResponse(ser.errors,status=400) elif request.method == "PATCH": data = JSONParser().parse(request) ser = CategorySerializer(instance=art,data=data,partial=True) #partial=True 意思是我要部分更新,默认是False if ser.is_valid(): ser.save() return JSONResponse(ser.data,status=201) return JSONResponse(ser.errors,status=400) elif request.method == "DELETE": art.delete() return HttpResponse(status=204)
1.5、postman测试运行:

二、 序列化高级用法
序列化高级用法:都是针对编辑 serializers.py 序列化文件,根据不同的高级用法,响应不同我们想要的结果, fields 关键字,表示你要响应显示什么字段,需要在我们的fields中定义,不管你在序列化类中定义多少字段,只要想显示都需要在fields 字段中定义。这个很重要,一定要记住。
2.1、StringRelatedField
说明:StringRelatedField将返回一个对应关系 model 的 __str__() 方法的字符串。
1、序列化文章(article),返回__str__() 方法的字符串
from rest_framework import serializers
from .models import Article,Category
#StringRelatedField获取 model 模型类中Category类的 def __str__中返回的值(self.name)
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.StringRelatedField() # modle模型Article中有category字段
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category') #新增显示category字段。
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name')
post请求结果:
GET: http://127.0.0.1:8000/api/article/2/
响应结果(response):
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": "监控中心" #category 显示的值是 模型类中 Catagory 中的 def __str__(self): return self.name。str()中 return 啥值,就返回什么值
}
2、序列化分类(catagory),反查文章(article),返回 str()方法字符串
from rest_framework import serializers
from .models import Article,Category
#StringRelatedField
class ArticleSerializer(serializers.ModelSerializer):
....
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.StringRelatedField(many=True) #因为查文章分类是多个对象,所以要加 many=True
class Meta:
model = Category
fields = ('id','name','articles') #article字段是在模型类Article中related_name中反射出来的
post请求结果:
GET: http://127.0.0.1:8000/api/category/1/
响应结果(reponse):
{
"id": 1,
"name": "资产管理",
"articles": [
"gaogege is very handsome",
"gaogege is very handsome",
"gaogege is very handsome",
"gaogege is very handsome",
"gaogege is very handsome"
]
}
2.2、PrimaryKeyRelatedField
说明:使用PrimaryKeyRelatedField 将返回一个对应关系的model的主键。
参数:
- queryset 用于在验证字段输入时模型实例查找。 关系必须明确设置 queryset,或设置 read_only = True
- many 如果是对应多个的关系,就设置为 True
- allow_null 如果设置为 True,则该字段将接受 None 的值或为空的关系的空字符串。默认为 False
- pk_field 设置为一个字段以控制主键值的序列化/反序列化。例如,pk_field = UUIDField(format ='hex') 将UUID主键序列化为紧凑的十六进制表示。
from rest_framework import serializers
from .models import Article,Category
# PrimaryKeyRelatedField
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(read_only=True) #read_only=True 是必须传的,不然会报错
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.PrimaryKeyRelatedField(read_only=True,many=True) #多个实例,一个分类下有多篇文章
class Meta:
model = Category
fields = ('id','name','articles')
post运行结果:
#请求文章article路由
GET:http://127.0.0.1:8000/api/article/2/
Reponse:
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": 2 #只显示category主键
}
#请求文章分类category路由
GET: http://127.0.0.1:8000/api/category/2/
Repose:
{
"id": 2,
"name": "监控中心",
"articles": [ #只显示articles主键
2
]
}
2.3、HyperlinkedRelatedField
说明:使用 HyperlinkedRelatedField 将返回一个超链接,该链接指向对应关系 model 的详细数据,view-name 是必选参数,为对应的视图生成超链接。
参数:
- view_name 用作关系目标的视图名称。如果使用的是标准路由器类,那么它的格式为 <modelname>-detail 的字符串
- queryset 验证字段输入时用于模型实例查询的查询器。关系必须明确设置 queryset,或设置 read_only = True
- many 如果应用于多对多关系,则应将此参数设置为 True
- allow_null 如果设置为 True,则该字段将接受 None 的值或为空的关系的空字符串。默认为 False
- lookup_field 应该用于查找的目标上的字段。应该对应于引用视图上的 URL 关键字参数。默认值为 pk
- lookup_url_kwarg 与查找字段对应的 URL conf 中定义的关键字参数的名称。默认使用与 lookup_field 相同的值
- format 如果使用 format 后缀,超链接字段将对目标使用相同的 format 后缀,除非使用 format 参数进行覆盖。
from rest_framework import serializers
from .models import Article,Category
#HyperlinkedRelatedField
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.HyperlinkedRelatedField(
view_name= 'category-detail', #urls路由的别名
lookup_field= 'id', #数据库字段的名字,这个字段到数据库中去找
read_only=True
)
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.HyperlinkedRelatedField(
view_name = 'article-detail',
lookup_field = "id",
many=True,
read_only=True
)
class Meta:
model = Category
fields = ('id','name','articles')
错误解决:
`HyperlinkedRelatedField` requires the request in the serializer context. Add `context={'request': request}` when instantiating the serializer.
在所有使用ArticleSerializer和CategorySerializer的地方加上context={'request': request},编辑视图views.py:
#序列化文章标题时,加上context={'request':request}
ser = ArticleSerializer(instance=art,context={'request':request})
#序列化分类时,加context={'request':request}参数
ser = CategorySerializer(instance=arts, many=True,context={'request':request})
post运行结果:
#访问文章标题
GET: http://127.0.0.1:8000/api/article/2/
运行结果;
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": "http://127.0.0.1:8000/api/category/2/"
}
#访问分类
GET:http://127.0.0.1:8000/api/category/2/
运行的结果:
{
"id": 2,
"name": "监控中心",
"articles": [
"http://127.0.0.1:8000/api/article/2/"
]
}
那我如果在根级路由写了一个别名,我想调用访问咋办啊,设置根级路由:
from django.urls import path, include
from app01 import views
urlpatterns = [
...
path('api/', include(('app02.urls', 'app02'), namespace="app02")) #根级路由设置命名空间
]
我在 serializers.py中的HyperlinkedRelatedField 这么使用:
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.HyperlinkedRelatedField(
view_name= 'app02:category-detail', #需要加上根级路由app02
...
)
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.HyperlinkedRelatedField(
view_name = 'app02:article-detail', #需要加上根级路由app02
...
)
2.4、SlugRelatedField
说明:使用 SlugRelatedField 将返回一个指定对应关系 model 中的字段,需要参数 slug_field 中指定字段名称。
参数:
- slug_field 应该用于表示目标的字段。这应该是唯一标识任何给定实例的字段。例如 username 。这是必选参数
- queryset 验证字段输入时用于模型实例查询的查询器。 关系必须明确设置 queryset,或设置 read_only = True
- many 如果应用于多对多关系,则应将此参数设置为 True
- allow_null 如果设置为 True,则该字段将接受 None 的值或为空的关系的空字符串。默认为 False
#SlugRelatedField
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(
read_only=True,
slug_field= 'name' #指定只返回模型类Category中的某个字段,这边我们返回name吧。
)
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.SlugRelatedField(
read_only=True,
slug_field='vum', #指定只返回模型类Article的vum字段
many=True
)
class Meta:
model = Category
fields = ('id','name','articles')
post运行结果:
#article文章路由
GET: http://127.0.0.1:8000/api/article/2/
运行结果:
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": "监控中心" #返回Catagory中的name值
}
#访问category分类路由
GET:http://127.0.0.1:8000/api/category/2/
运行结果;
{
"id": 2,
"name": "监控中心",
"articles": [ #返回Article中的vum值
12
]
}
2.4、HyperlinkedIdentityField
说明:使用 HyperlinkedIdentityField 将返回指定 view-name 的超链接的字段。
参数:
- view_name 应该用作关系目标的视图名称。如果您使用的是标准路由器类,则它将是格式为 <model_name>-detail的字符串。必选参数
- lookup_field 应该用于查找的目标上的字段。应该对应于引用视图上的 URL 关键字参数。默认值为 pk
- lookup_url_kwarg 与查找字段对应的 URL conf 中定义的关键字参数的名称。默认使用与 lookup_field 相同的值
- format 如果使用 format 后缀,超链接字段将对目标使用相同的 format 后缀,除非使用 format 参数进行覆盖
# HyperlinkedIdentityField
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.HyperlinkedIdentityField(
view_name= "category-detail", #view_name是必须传的
lookup_field= 'id' #默认是pk
)
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
class CategorySerializer(serializers.ModelSerializer):
articles = serializers.HyperlinkedIdentityField(
view_name= "article-detail",
many=True
)
class Meta:
model = Category
fields = ('id','name','articles')
post运行结果:
#article文章路由
GET: http://127.0.0.1:8000/api/article/2/
运行结果:
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": "http://127.0.0.1:8000/api/category/2/"
}
#访问category分类路由
GET:http://127.0.0.1:8000/api/category/2/
运行结果;
{
"id": 2,
"name": "监控中心",
"articles": [
"http://127.0.0.1:8000/api/article/2/"
]
}
三、HyperlinkedModelSerializer
说明:HyperlinkedModelSerializer 类与 ModelSerializer 类相似,只不过它使用超链接来表示关系而不是主键。用这个序列化的时候,必须继承的是HyperlinkedModelSerializer,而不是 ModelSerializer了。
#HyperlinkedModelSerializer
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Article
fields = "__all__"
extra_kwargs = {
'url': {'view_name': 'article-detail', 'lookup_field': 'id'},
'category': {'view_name': 'category-detail', 'lookup_field': 'id'},
}
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = ('id','name','articles','url') #url字段自己添加
extra_kwargs = {
'url': {'view_name': 'category-detail', 'lookup_field': 'id'},
'articles': {'view_name': 'article-detail', 'lookup_field': 'id'},
}
注意:
使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数---字典格式
extra_kwargs = {
'vnum': {'min_value': 0, 'required': True},
}
postman运行结果:
#article文章路由
GET: http://127.0.0.1:8000/api/article/2/
运行结果:
{
"url": "http://127.0.0.1:8000/api/article/2/",
"title": "gaogege is very handsome",
"vum": 12,
"content": "that is very error",
"category": "http://127.0.0.1:8000/api/category/2/"
}
#访问category分类路由
GET:http://127.0.0.1:8000/api/category/2/
运行结果;
{
"id": 2,
"name": "监控中心",
"articles": [
"http://127.0.0.1:8000/api/article/2/"
],
"url": "http://127.0.0.1:8000/api/category/2/"
}
看到了吧,如果你重新定义字段的话,需要在 extra_kwargs 中通过字典的方式修改,跟ModelSerializer是不一样的。
四、 嵌套序列化关系模型
顾名思义就是序列化里面有另一个序列化类。这要强调一下,序列化嵌套,只能一方嵌套一方,不能相互嵌套。
#序列化嵌套
class ArticleSerializer(serializers.ModelSerializer):
#category = CategorySerializer() 这边不能嵌套CategorySerializer(),会报CategorySerializer没有定义错误
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
class CategorySerializer(serializers.ModelSerializer):
articles = ArticleSerializer(many=True) #所以只能这边嵌套序列化关系
class Meta:
model = Category
fields = ('id','name','articles') #articles先通过文章模型(Article类)去找文章序列化,系列化哪些字段,这边是全局字段
postman运行结果:
GET: http://127.0.0.1:8000/api/category/1/
运行结果:
{
"id": 2,
"articles": [ #关联的文章信息全部显示出来
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": 2
}
],
"name": "监控中心"
}
序列化嵌套: 会去找对应的模型类(Modles),然后再去序列化出来。
五、深度遍历:depth
depth:这个字段可以用来深度遍历。就是继续往下找,官网上最多深度遍历10层,但是一般建议 2-3层,但是只是叠加数据返回量。
#序列化嵌套
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
depth = 2 #表示深度查找2层
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name','articles')
postman运行结果:
GET:http://127.0.0.1:8000/api/article/2/
运行结果:
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": { #深度显示详细数据
"id": 2,
"name": "监控中心"
}
}
六、自定义属性:SerializerMethodField
说明:通过这个属性我们可以自定义一些属性。比如说我们要统计 count字段等。
class CategorySerializer(serializers.ModelSerializer):
#articles = ArticleSerializer(many=True)
count = serializers.SerializerMethodField() #自定义序列化方法字段count
class Meta:
model = Category
fields = ('id','name','articles','count') #加上count字段
def get_count(self,obj): #obj指得是model模型Category类对象
return obj.articles.count() #articles反查的字段
上述代码说明:
count = serializers.SerializerMethodField() #自定义方法字段 fields = (...,'count') #count这边需要作为响应显示 def get_count(self,obj) => 方法名:get_字段名。obj:指的是当前序列化类对应的模型类这里是Category的对象。
postman运行结果:
GET:http://127.0.0.1:8000/api/category/2/
运行结果:
{
"id": 2,
"name": "监控中心",
"articles": [
2
],
"count": 1 #返回字段的值
}
七、 自定义数据源:source
序列化的时候指定数据源
7.1、数据来源(source)是外键中的某个字段的值
#source
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.CharField(source="category.name") #数据来源是Category类中的name值
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category')
postman请求运行结果:
GET:http://127.0.0.1:8000/api/article/2/
运行结果:
{
"id": 2,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": "监控中心" #数据来源是category类中的name值
}
7.2、数据来源(source)是外键中的所有字段的值
#source
class ArticleSerializer(serializers.ModelSerializer):
.....
class CategorySerializer(serializers.ModelSerializer):
arts = serializers.CharField(source="articles.all") # related反查的情况下用articles.all
#arts = serializers.CharField(source="articles_set.all") #没有related反查的情况下用articles_set.all
class Meta:
model = Category
fields = ('id','name','articles','arts') #添加arts字段
postman请求运行结果:
GET: http://127.0.0.1:8000/api/category/2/
运行结果:
{
"id": 2,
"name": "监控中心",
"articles": [
2
],
"arts": "<QuerySet [<Article: gaogege is very handsome>]>" #获取的是 QuerySet 对象
}
但是我们不是需要返回的一个QuerySet的对象,我们想要的是数据,所以我们对显示的数据需要用to_representation方法重写:
#source
class MyCharField(serializers.CharField):
def to_representation(self, value): #value 就是 articles.all中所有的值
data_list = []
for row in value:
data_list.append({'title': row.title, 'content': row.content})
return data_list #必须要有返回值
....
class CategorySerializer(serializers.ModelSerializer):
arts = MyCharField(source="articles.all") #MyCharField需要跟上面自定义的一样
class Meta:
model = Category
fields = ('id','name','articles','arts')
postman请求运行结果:
GET: http://127.0.0.1:8000/api/category/2/
运行结果:
{
"id": 2,
"name": "监控中心",
"articles": [
2
],
"arts": [
{
"title": "gaogege is very handsome",
"content": "that is very error"
}
]
}
7.3、利用source实现可读可写
from collections import OrderedDict
class ChoiceDisplayField(serializers.Field):
"""Custom ChoiceField serializer field."""
def __init__(self, choices, **kwargs):
"""init."""
self._choices = OrderedDict(choices)
super(ChoiceDisplayField, self).__init__(**kwargs)
# 返回可读性良好的字符串而不是 1,-1 这样的数字
def to_representation(self, obj):
"""Used while retrieving value for the field."""
return self._choices[obj]
def to_internal_value(self, data):
"""Used while storing value for the field."""
for i in self._choices:
# 这样无论用户POST上来但是CHOICES的 Key 还是Value 都能被接受
if i == data or self._choices[i] == data:
return i
raise serializers.ValidationError("Acceptable values are {0}.".format(list(self._choices.values())))
八、 to_representation方法(多对多关系):自定义字段格式显示
序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。
8.1、模型定义
说明:增加Tag表,实现Article 和 Tag 产生多对多关系。
from django.db import models
class Article(models.Model):
title = models.CharField(verbose_name='标题', max_length=100)
vum = models.IntegerField(verbose_name='浏览量')
content = models.TextField(verbose_name='内容')
category = models.ForeignKey(to="Category",on_delete=models.CASCADE,related_name="articles") #related_name反查
tags = models.ManyToManyField(to="Tag",related_name="articles") #related_name反查
def __str__(self):
return self.title
class Category(models.Model):
name = models.CharField(verbose_name="分类",max_length=10)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(verbose_name="标签名字",max_length=10)
create_time = models.DateTimeField()
def __str__(self):
return self.name
8.2、序列化
说明:编写serializers.py,增加Tags序列化
# to_representation方法
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category','tags')
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name','articles')
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('id','name','create_time')
8.3、路由定义
说明:定义路由 app02 -> urls.py
from django.urls import path
from app02 import views
urlpatterns = [
....
path("tag/", views.tag_list, name="tag-list"),
path("tag/<int:id>/", views.tag_detail, name="tag-detail")
]
8.3、视图
说明:跟上面一样,增加Tag的视图函数
from .serializers import ArticleSerializer,CategorySerializer,TagSerializer .... from .models import Article,Category,Tag ... # Create your views here. class JSONResponse(HttpResponse): .... .... @csrf_exempt def tag_list(request): if request.method == "GET": arts = Tag.objects.all() ser = TagSerializer(instance=arts, many=True,context={'request':request}) return JSONResponse(ser.data, status=200) elif request.method == "POST": data = JSONParser().parse(request) ser = TagSerializer(data=data) if ser.is_valid(): ser.save() return JSONResponse(ser.data, status=201) return JSONResponse(ser.errors,status=401) @csrf_exempt def tag_detail(request,id): try: art = Tag.objects.get(id=id) except Tag.DoesNotExist as e: return HttpResponse(status=404) if request.method == "GET": ser = TagSerializer(instance=art,context={'request':request}) return JSONResponse(ser.data,status=200) elif request.method == "PUT": data = JSONParser().parse(request) ser = TagSerializer(instance=art,data=data,context={'request':request}) if ser.is_valid(): ser.save() return JSONResponse(ser.data,status=201) return JSONResponse(ser.errors,status=400) elif request.method == "PATCH": data = JSONParser().parse(request) ser = TagSerializer(instance=art,data=data,partial=True,context={'request':request}) if ser.is_valid(): ser.save() return JSONResponse(ser.data,status=201) return JSONResponse(ser.errors,status=400) elif request.method == "DELETE": art.delete() return HttpResponse(status=204)
8.4、初始化数据库
>python manage.py makemigrations >python manage.py migrate
8.5、造tags数据

8.6、更改数据展示
class TagSerializer(serializers.ModelSerializer):
create_time = serializers.DateTimeField(format='%Y-%m-%d') #时间展示
class Meta:
model = Tag
fields = ('id','name','create_time')
postman执行数据
POST: http://127.0.0.1:8000/api/tag/
入参:
{
"name": "标签四",
"create_time": "2020-04-26 20:20:20"
}
出参:
{
"id": 4,
"name": "标签四",
"create_time": "2020-04-26" #显示格式改变
}
8.6、增加多对多数据

8.7、depth深度显示
说明:深度显示只支持序列化,但是不支持反序列化。意思就是:能获取数据(get),但是想要插入数据或者更新数据(post、put、patch)就不可以了。
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category','tags')
depth = 2 #深度显示,只支持序列化(get),不支持反序列化(post、patch、put)
运行结果:

8.8、to_representation方法
说明:depath只能解决序列化问题,但是不能解决反序列化问题,所以这个时候我们就要用到to_representation方法。序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。也就是说具体的返回的值是由to_representation方法决定的,它需要传入一个参数instance,表示当前的 实例对象。
# to_representation方法
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ("id", 'vum', 'content', 'title','category','tags')
#depth = 2
#决定每个字段的返回值
def to_representation(self, instance): #这边就是Article的model的实例
representation = super(ArticleSerializer, self).to_representation(instance)
representation['category'] = CategorySerializer(instance.category).data
representation['tags'] = TagSerializer(instance.tags, many=True).data #这边tags 想返回哪些字段是TagSerializer中的fields决定的
return representation
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id','name','articles')
class TagSerializer(serializers.ModelSerializer):
create_time = serializers.DateTimeField(format='%Y-%m-%d') #时间展示
class Meta:
model = Tag
fields = ('id','name','create_time')
postman运行结果:
1、新增数据post方法:
POST:http://127.0.0.1:8000/api/article/
入参:
{
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": 2,
"tags": [1,2,3,4]
}
出参:
{
"id": 10,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": {
"id": 2,
"name": "监控中心",
"articles": [
2,
8,
9,
10
]
},
"tags": [
{
"id": 1,
"name": "标签一",
"create_time": "2020-04-26"
},
{
"id": 2,
"name": "标签二",
"create_time": "2020-04-26"
},
{
"id": 3,
"name": "标签三",
"create_time": "2020-04-26"
},
{
"id": 4,
"name": "标签四",
"create_time": "2020-04-26"
}
]
}
2、获取数据GET方法:
GET:http://127.0.0.1:8000/api/article/9/
出参:
{
"id": 9,
"vum": 12,
"content": "that is very error",
"title": "gaogege is very handsome",
"category": {
"id": 2,
"name": "监控中心",
"articles": [
2,
8,
9,
10
]
},
"tags": [
{
"id": 1,
"name": "标签一",
"create_time": "2020-04-26"
},
{
"id": 2,
"name": "标签二",
"create_time": "2020-04-26"
}
]
}
"id": 3,
"name": "标签三",
"create_time": "2020-04-26"
},
{
"id": 4,
"name": "标签四",
"create_time": "2020-04-26"
}
]
}

浙公网安备 33010602011771号