参考链接:https://www.cnblogs.com/liwenzhou/p/8543035.html
APIView基础序列化类:https://www.cnblogs.com/Rivend/p/12057767.html
视图路由进阶:https://www.cnblogs.com/Rivend/p/12057803.html
serializers.Serializer
单表的GET和POST:
路由:
url(r'source/', views.SourceView.as_view()),
序列化类:
from rest_framework import serializers
from rest_framework.response import Response
# 为queryset, model对象做序列化,只要你定义了name和addr我都能给你反序列化,name和addr对应数据库中的值
class PublishSerializers(serializers.Serializer):
name = serializers.CharField()
addr = serializers.CharField()
视图:
from rest_framework.views import APIView
#使用
class PublishView(APIView):
# 查询数据
def get(self, request):
# first inquire database
publish = models.Publisher.objects.all()
# data put serializers data packging
bs = PublishSerializers(publish, many=True) # many=True多个对象
# return
return Response(bs.data)
推荐写法:
class SourceView(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
all_source = models.Source.objects.all()
ser_obj = SourceSerializer(all_source, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = SourceSerializer(data=request.data)
if ser_obj.is_valid():
# 数据没问题
ser_obj.save()
return Response(res)
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
外键的GET和POST:
路由:
url(r'comment/', views.Comment.as_view()),
序列化:
class BookSerializers(serializers.Serializer):
title = serializers.CharField()
pub_date = serializers.DateField()
# 反序列化一对多字段返回的是__str__数据
publish = serializers.CharField(source="publish.addr") # source 可以指定返回的一对多的字段
# authors=serializers.CharField(source="authors.all") # 指定序列化多对多的字段(不推荐)
authors = serializers.SerializerMethodField()
# 多对多字段序列化方法,这个函数必须是get_authors,因为这个字段在是多对多
def get_authors(self, obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
视图:
#使用
class PublishView(APIView):
# 查询数据
def get(self, request):
# first inquire database
publish = models.Publisher.objects.all()
# data put serializers data packging
bs = BookSerializers(publish, many=True) # many=True多个对象
# return
return Response(bs.data)
class Comment(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
all_data = models.Comment.objects.all()
ser_obj = CommentSerializer(all_data, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = CommentSerializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
serializers.ModelSerializer
ModelSerializer
与Serializer
区别在于:
ModelSerializer
支持了Serializer
中所有的操作,并且通过自动生成所有数据字段与序列化类的一一对应关系,而不用自己手动添加。
即Serializer
是ModelSerializer
的父类,所以ModelSerializer
才会支持Serializer
的所有操作.
好处:
ModelSerializer已经重载了create与update方法,它能够满足将post或patch上来的数据进行进行直接地创建与更新,
除非有额外需求,那么就可以重载create与update方法。
ModelSerializer在Meta中设置fields字段,系统会自动进行映射,省去每个字段再写一个field。
序列化原理:
"""
序列化原理BookSerializers(book_list,many=Ture):
temp=[]
for obj in book_list:
temp.append({
"title":obj.title,
"price":str(obj.publish), #obj.publish.name
"author":get_authors(obj),
})
"""
单表的GET和POST:
路由:
urlpatterns = [
url(r'articlelinked/', views.ArticleLinked.as_view()),,
url(r'source/(?P<pk>\d+)', views.SourceDetailView.as_view(), name='source-detail'),
]
序列化类:
class PublishModelSerializers(serializers.ModelSerializer):
class Meta:
model = models.Publisher
fields = "__all__" # 表示所有字段
# exclude = ('add_time',): 除去指定的某些字段
# 定义报错信息
# extra_kwargs = {
# "content": {"error_messages": {"required": "评论内容不能为空"}},
# "article": {"error_messages": {"required": "文章不能为空"}}
# }
class SourceSerializer(serializers.ModelSerializer):
def validate_name(self, value):
if '草' in value:
raise ValidationError('不符合社会主义核心价值观')
return value
class Meta:
model = models.Source
fields = "__all__"
class CourseDetailSerializer(serializers.ModelSerializer):
# # one2one/fk/choice 跨表查询 或者外间选择项
name = serializers.CharField(source='course.name')
img = serializers.CharField(source='course.course_img') # 选择项
level = serializers.CharField(source='course.get_level_display')
# m2m
recommend_courses = serializers.SerializerMethodField()
teachers = serializers.SerializerMethodField()
# FK reverse 跨表反向查询
coursechapter = serializers.SerializerMethodField()
#
class Meta:
model = models.CourseDetail
fields = ['id', 'hours', 'course_slogan', 'video_brief_link', 'why_study', 'what_to_study_brief',
'career_improvement', 'prerequisite', 'name', 'level', 'img', 'recommend_courses', 'teachers',
'coursechapter']
# fields = '__all__'
def get_recommend_courses(self, obj):
"""获取推荐的所有课程"""
queryset = obj.recommend_courses.all()
return [{'id': row.id, 'name': row.name} for row in queryset]
def get_teachers(self, obj):
"""获取所有老师"""
obj = obj.teachers.all()
return [{'id': row.id, 'name': row.name} for row in obj]
def get_coursechapter(self, obj):
"""获取所有章节"""
obj = obj.course.coursechapters.all()
return [{'id': row.id, } for row in obj]
视图:
查询所有数据:
class PublishView(APIView):
# 查询数据
def get(self, request):
# first inquire database
publish = models.Publisher.objects.all()
# data put serializers data packging
bs = PublishModelSerializers(publish, many=True) # many=True多个对象
# return
return Response(bs.data)
# 增加数据
def post(self, request):
bs = PublishModelSerializers(data=request.data) # post不需要定义many=Ture
if bs.is_valid():
bs.save() # 保存
return Response("添加成功")
else:
return Response("增加失败")
查询单条数据:
class PublishDetaiView(APIView):
# 将这个pk设置成和lookup_url_kwarg='pk' 一样的值,不然加后缀会取不到值
def get(self, request, pk): # id 不要放到request前面
# 查询数据库
publish = models.Publisher.objects.filter(pk=pk)
# 封装打包序列化数据
bs = PublishModelSerializers(publish, many=True) # many=True多个对象
# Response 会直接返回josn数据格式
return Response(bs.data)
# # 修改数据(前端指定id值后,在data中输入k:v即可change数据)
def put(self, request, pk):
# inquire database
publish = models.Publisher.objects.filter(pk=pk).first()
# data= form request.data client
ps = PublishModelSerializers(publish, data=request.data, many=True) # many=True多个对象
# if ps pass verify
if ps.is_valid():
ps.save()
return Response(ps.data)
else:
return Response(ps.errors)
# 删除数据
def delete(self, request, pk):
models.Publisher.objects.filter(pk=pk).delete()
return Response("删除成功")
推荐写法:
class ArticleList(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
article_list = models.Article.objects.all()
ser_obj = ArticleSerializer(article_list, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = ArticleWriteSerializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
自定义字段超链接路径:
路由:
urlpatterns = [
re_path(r"^Books/$", views.BookView.as_view(), name='book'),
re_path(r"^Book/(?P<id>\d+)/$", views.BookDetaiView.as_view(), name='books'),
]
序列化:
from rest_framework import serializers
class BookModelSerializers(serializers.ModelSerializer):
# 自定义publish字段超链接路径
depth = 1 # 0 ~ 10
publish = serializers.HyperlinkedIdentityField(view_name='books',
lookup_field='publish_id',
lookup_url_kwarg='id')
"""
# view_name 参数 进行传参的时候是参考路由匹配中的name与namespace参数.
# lookeup_field 参数是根据在UserInfo表中的连表查询字段group_id.
# look_url_kwarg 参数在做url反向解析的时候会用到.
"""
class Meta:
model = Book
# fields = ['id', 'title', 'pub_date', 'publish', 'authors']# 这个是可以自定义字段的
fields = "__all__"
depth = 0
# 自动向内部进行深度查询,就是查询的比较详细 depth表示查询层数
视图:
查询所有:
class BookView(APIView):
def get(self, request, *args, **kwargs):
book_list = Book.objects.all()
# context十分关键,如果不将request传递给它,在序列化的时候,图片与文件这些Field不会再前面加上域名,也就是说,只会有/media/img...这样的路径!
bs = BookModelSerializers(instance=book_list, many=True, context={'request': request}) # 在做链接的时候需要添加context参数
print(bs)
# 默认就返回json格式的字符串
return Response(bs.data)
# 其他还未实现
查询单条:
class BookDetaiView(APIView):
# inquire database
def get(self, request, id, *args, **kwargs):
book_list = Book.objects.filter(id=id)
bs = BookModelSerializers(instance=book_list, many=True, context={'request': request}) # 在做链接的时候需要添加context参数
print(bs)
# 默认就返回json格式的字符串
return Response(bs.data)
推荐写法:
class ArticleLinked(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
article_list = models.Article.objects.all()
ser_obj = ArticleHyperlinkedSerializer(article_list, many=True, context={'request': request})
res["data"] = ser_obj.data
return Response(res)
重写save中的create方法
# 重写save中的create方法2
def create(self, validated_data):
print(validated_data["title"], validated_data["pub_date"], validated_data["publish"])
publish_id = validated_data["publish"]
book = models.Book.objects.create(title=validated_data["title"], pub_date=validated_data["pub_date"],
publish=publish_id)
book.authors.add(*validated_data["authors"])
return book
实例代码:
class BookModelSerializers(serializers.ModelSerializer):
# 自定义publish字段超链接路径
publish_url = serializers.HyperlinkedIdentityField(view_name='detailpublish',
lookup_field='publish_id',
lookup_url_kwarg='pk',
)
publish = serializers.CharField(source="publish.id")
"""
# view_name参数 进行传参的时候是参考路由匹配中的name与namespace参数
# lookeup_field参数是根据在UserInfo表中的连表查询字段group_id
# look_url_kwarg参数在做url反向解析的时候会用到
"""
# 重写save中的create方法
def create(self, validated_data):
# create 方法之前也可以单独pop在添加
"""
author = validated_data.pop[title]
然后再进行额外自己添加
obj = Book.objecte.create(**validated_data)
obj.authors.add(*authors)
"""
publish_id = validated_data["publish"]["id"]
book = models.Book.objects.create(title=validated_data["title"], pub_date=validated_data["pub_date"],
publish=models.Publisher.objects.filter(pk=publish_id).first()
)
book.authors.add(*validated_data["authors"])
return book
class Meta:
model = models.Book
# fields = ['id', 'title', 'pub_date', 'publish', 'authors']
fields = "__all__"
depth = 0 ## 0 ~ 10
# 自动向内部进行深度查询,就是查询的比较详细 depth表示查询层数