参考链接: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表示查询层数