ModelSerializer 和 serializers

serializers序列化:普通字段

# 一.定义一个反序列的类
from rest_framework import serializers
from rest_framework.response import Response


# 为queryset, model对象做序列化,只要你定义了name和addr我都能给你反序列化
class PublishSerializers(serializers.Serializer):
    name = serializers.CharField()
    addr = serializers.CharField()
#使用
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)

serializers序列化:一对多,多对多

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)

ModelSerializer
在大多数情况下,我们都是基于model字段去开发。

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),
            
            })

"""
# 定义一个model类
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 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 BookModelSerializers(serializers.ModelSerializer):
    # 自定义publish字段超链接路径
    # depth = 1  # 0 ~ 10
    # publish = serializers.HyperlinkedIdentityField(view_name='detailpublish',
    #                                                lookup_field='publish_id',
    #                                                lookup_url_kwarg='pk')

    """
    # view_name参数 进行传参的时候是参考路由匹配中的name与namespace参数
    #  lookeup_field参数是根据在UserInfo表中的连表查询字段group_id
    # look_url_kwarg参数在做url反向解析的时候会用到
    """

    class Meta:
        model = models.Book
        # fields = ['id', 'title', 'pub_date', 'publish', 'authors']# 这个是可以自定义字段的
        fields = "__all__"
        depth = 0
        # 自动向内部进行深度查询,就是查询的比较详细  depth表示查询层数
class BookView(APIView):
    def get(self, request, *args, **kwargs):
        book_list = models.Book.objects.all()
        # context十分关键,如果不将request传递给它,在序列化的时候,图片与文件这些Field不会再前面加上域名,也就是说,只会有/media/img...这样的路径!
        bs = BookModelSerializers(instance=book_list, many=True)  # 在做链接的时候需要添加context参数
        print(bs)
        # 默认就返回json格式的字符串
        return Response(bs.data)

    # 其他还未实现

    


class BookDetaiView(APIView):
    # inquire database
    def get(self, request, id, *args, **kwargs):
        book_list = models.Book.objects.filter(id=id)
        bs = BookModelSerializers(instance=book_list, many=True)  # 在做链接的时候需要添加context参数
        print(bs)
        # 默认就返回json格式的字符串
        return Response(bs.data)

        # 其他还未实现
自定义字段超链接路径
class BookModelSerializers(serializers.ModelSerializer):
    # 自定义publish字段超链接路径
    depth = 1  # 0 ~ 10
    publish = serializers.HyperlinkedIdentityField(view_name='detailpublish',
                                                   lookup_field='publish_id',
                                                   lookup_url_kwarg='pk')

    """
    # view_name参数 进行传参的时候是参考路由匹配中的name与namespace参数
    #  lookeup_field参数是根据在UserInfo表中的连表查询字段group_id
    # look_url_kwarg参数在做url反向解析的时候会用到
    """

    class Meta:
        model = models.Book
        # fields = ['id', 'title', 'pub_date', 'publish', 'authors']
        fields = "__all__"
        depth = 0
        # 自动向内部进行深度查询,就是查询的比较详细  depth表示查询层数

总结:

1.request类---------源码

2.restframework 下的APIView

re_path('^books/$', views.BookView.as_view(),name="book"),  # View(request) ======APIView:dispatch()

  books/一旦被访问: view(request) ---------dispatch()

3.dispatch()

  构建request对象

  self.request=Request(request)

  self.request._request

  self.request._GET

  self.request._data  # POST  PUT

  分发-------get请求(源码)

     if request.method.lower() in self.http_method_names:
            # self = Publish,反射类中的get方法如果有我就封装到handler里面,如果你没有定义方法我我也就返回一个错误信息
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            # <HttpResponseNotAllowed [OPTIONS] status_code=405, "text/html; charset=utf-8">
            handler = self.http_method_not_allowed
            #也就是说这个地方要么就是调用我Publish的get方法和post方法,要不就抛错误信息
        return handler(request, *args, **kwargs)  #self.get
      # 相当于调用了get()方法的response

4. 序列化类

 # from django,core import serializers

# ret = serializers.serialize("json",publish_list)

  restframework下的序列化类

    将queryset或者model对象序列化成一个json数据

      bs = BookModelSerializers(instance=book_list, many=True, context={'request': request})  # 在做链接的时候需要添加context参数
      # 默认就返回json格式的字符串
      return Response(bs.data)
      还可以做校验数据, json ------> queryset/model------》记录
        ps = PublishModelSerializers(publish, data=request.data, many=True)  # many=True多个对象
        # 做校验数据
        if ps.is_valid():
            ps.save()
            return Response(ps.data)
        else:
            return Response(ps.errors)

5.操作数据(例)

    

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数据格式
        ret = Response(bs.data)
        # print(ret,6666666666666666666666666)
        return ret

    # #  修改数据(前端指定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("删除成功")

      


    

猜你喜欢

转载自www.cnblogs.com/Rivend/p/11823763.html