• 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表示查询层数
  • 相关阅读:
    【Appium】appium踩坑记录:解决每次安装appium setting和Unlock
    Pycharm from XXX import XXX 引入本地文件标红报错(source_path&Python package)
    🍖02 不同平台更换pip源
    🍖pycharm 更换 pip 下载源
    🍖01 路飞学城项目分析
    🍖Vue-cli 创建项目
    🍖Vue 与后端交互
    🍖Vue 计算属性
    🍖Vue 虚拟DOM与Diff算法简介
    🍖Vue 生命期钩子
  • 原文地址:https://www.cnblogs.com/Rivend/p/12055934.html
Copyright © 2020-2023  润新知