Django REST framework序列化

参考链接: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

ModelSerializerSerializer区别在于

ModelSerializer支持了Serializer中所有的操作,并且通过自动生成所有数据字段与序列化类的一一对应关系,而不用自己手动添加。
SerializerModelSerializer的父类,所以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表示查询层数
posted @ 2019-12-17 17:58  Mr_Riven  阅读(277)  评论(0)    收藏  举报