Django中的序列化器

什么是序列化

Django 中的序列化器(Serializer)是用于在数据模型(Model)和其他格式(如 JSON)之间进行数据转换的工具。序列化器允许你将数据对象转换为可序列化的格式,以便在网络传输、存储或渲染到模板中使用。


简单来说:就是将从数据库取出的数据进行包装,然后发送给前端。

Serializer

Serializer 是一个基础类,用于手动定义数据序列化和反序列化的过程。你可以继承 Serializer 类并定义字段、验证规则和自定义序列化逻辑。这个类提供了一些基本方法。

 

实际开发中

公共基础序列化器

首先我们会在公共utils中写好一些基础的Serializers。

1、BaseSerializer 是一个基础的序列化器类,它接收一个对象 obj 作为参数,并提供了一个默认的 to_dict() 方法,返回一个空字典。可以在该类的子类中重写 to_dict() 方法,根据需要自定义数据转换逻辑。

class BaseSerializer(object):
​
    def __init__(self, obj):
        self.obj = obj
​
    def to_dict(self):
        return {}
        

2、MetaSerializer 是用于表示分页元数据的序列化器类。它接收当前页 page、总页数 page_count 和总记录数 total_count 作为参数,并提供了一个 to_dict() 方法,将这些元数据转换为字典格式。

class MetaSerializer(object):
    """ 分页元数据 """
    def __init__(self, page, page_count, total_count, **kwargs):
        """
        :param page: 当前页
        :param page_count: 总页数
        :param total_count: 总记录数
        """
        self.page = page
        self.page_count = page_count
        self.total_count = total_count
​
    def to_dict(self):
        return {
            'total_count': self.total_count,
            'page_count': self.page_count,
            'current_page': self.page
        }
​

3、BaseListPageSerializer 是一个封装了分页数据的序列化器类。它接收当前页的对象 page_obj、分页器的对象 paginator 和当前页的数据列表 object_list 作为参数。该类提供了一个 to_dict() 方法,将分页数据传递给MetaSerializer()转换为字典格式。然后将Meta数据和取到的objects封装好一起返回给前端。子类需要重写get_object()传递要取的参数

class BaseListPageSerializer(object):
    """ 分页类封装 """
    def __init__(self, page_obj, paginator=None, object_list=[]):
        """
        :param page_obj: 当前页的对象
        :param paginator: 分页器的对象
        :param object_list: 当前页的数据列表
        """
        self.page_obj = page_obj
        self.paginator = paginator if paginator else page_obj.paginator
        self.object_list = object_list if object_list else page_obj.object_list
​
    def get_object(self, obj):
        """ 对象的内容,子类重写 """
        return {}
​
    def to_dict(self):
        page = self.page_obj.number
        page_count = self.paginator.num_pages
        total_count = self.paginator.count
        meta = MetaSerializer(page=page, page_count=page_count, total_count=total_count).to_dict()
​
        objects = []
        for obj in self.object_list:
            objects.append(self.get_object(obj))
        return {
            'meta': meta,
            'objects': objects
        }

继承基础序列化器

1、继承列表序列化器

  • SightListSerializer 是继承自 BaseListPageSerializer 的具体序列化器类,用于序列化景点列表数据。

  • SightListSerializer 中,重写了父类的 get_object() 方法。该方法接收一个景点对象 obj,并将其转换为字典格式的数据。

  • get_object() 方法中,根据具体的需求,从景点对象 obj 中提取需要的字段,并将它们添加到一个字典中。在示例代码中,提取了景点的 idnamemain_img(主要图片的 URL)、scoreprovincemin_pricecity 字段,并设置了 comment_count 为固定值 0(评论数量暂时无法获取)。

  • 通过这种方式,SightListSerializer 将每个景点对象转换为包含特定字段的字典格式数据。在 to_dict() 方法中,通过调用 get_object() 方法处理当前页的每个景点对象,并将转换后的数据添加到 objects 列表中。最后,将分页元数据对象列表组装成一个字典,并返回结果。

class SightListSerializer(BaseListPageSerializer):
    """景点列表"""
​
    def get_object(self, obj):
        return {
            'id': obj.id,
            'name': obj.name,
            'main_img': obj.main_img.url,
            'score': obj.score,
            'province': obj.province,
            'min_price': obj.min_price,
            'city': obj.city,
            # TODO 评论数量暂时无法获取
            'comment_count': 0
        }
​

对应接口

class SightListView(ListView):
    """ 景点列表 """
    # 每页放5条数据
    paginate_by = 5
​
    def get_queryset(self):
        """ 重写查询方法 """
        query = Q(is_valid=True)
        # 1. 热门景点
        is_hot = self.request.GET.get('is_hot', None)
        if is_hot:
            query = query & Q(is_hot=True)
        # 2. 精选景点
        is_top = self.request.GET.get('is_top', None)
        if is_top:
            query = query & Q(is_top=True)
        # TODO 3. 景点名称搜索
        queryset = Sight.objects.filter(query)
        return queryset
​
    def render_to_response(self, context, **response_kwargs):
        print(context)
        page_obj = context['page_obj']
        if page_obj is not None:
            data = serializers.SightListSerializer(page_obj).to_dict()
            return http.JsonResponse(data)
        else:
            return NotFoundJsonResponse()

2、继承基础序列化器

  • SightDetailSerializer 是继承自 BaseSerializer 的具体序列化器类,用于序列化景点详情数据。

  • SightDetailSerializer 中,重写了父类的 to_dict() 方法。该方法将景点对象 self.obj 的字段转换为字典格式的数据。

  • to_dict() 方法中,根据具体的需求,从景点对象 self.obj 中提取需要的字段,并将它们添加到一个字典中。在示例代码中,提取了景点的 idnamedescimg(横幅图片的 URL)、contentscoreprovincemin_pricecityareatown 字段,并设置了 comment_count 为固定值 0(评论数量暂时无法获取)。

class SightDetailSerializer(BaseSerializer):
    """景点详情"""
​
    def to_dict(self):
        obj = self.obj
        return {
            'id': obj.id,
            'name': obj.name,
            'desc': obj.desc,
            'img': obj.banner_img.url,
            'content': obj.content,
            'score': obj.score,
            'province': obj.province,
            'min_price': obj.min_price,
            'city': obj.city,
            'area': obj.area,
            'town': obj.town,
            # TODO 评论数量暂时无法获取
            'comment_count': 0
​
        }
​
​

对应接口

class SightDetailView(DetailView):
    """ 景点详情 """
    #DetailView会自动匹配pk
    def get_queryset(self):
        return Sight.objects.all()
​
    def render_to_response(self, context, **response_kwargs):
        page_obj = context['object']
        if page_obj is not None:
            if page_obj.is_valid == False:
                return NotFoundJsonResponse()
            data = serializers.SightDetailSerializer(page_obj).to_dict()
            return http.JsonResponse(data)
        return NotFoundJsonResponse()
 
posted @ 2023-06-14 17:21  qfzwy  阅读(799)  评论(0)    收藏  举报