【问题标题】:How to Add Attribute to Django QuerySet That Will Get Serialized?如何将属性添加到将被序列化的 Django QuerySet?
【发布时间】:2023-03-07 06:56:01
【问题描述】:

我有两个 Django 1.8 模型,它们代表列表和列表中的项目。我还有一个视图,它使用 Django REST 框架充当 REST 端点和一个包含调用此端点的 jQuery Ajax 块的模板。此视图获取特定用户拥有的所有列表,并查看给定项目是否在任何列表中。每当它找到这样的项目时,它应该向传递回模板的数据添加一个“in_list”属性。我遇到的问题是,虽然我可以将这个额外的“in_list”属性添加到列表中,但它不会被序列化程序拾取并添加到序列化数据中。代码如下:

# views.py
def get_viewer_lists_checked(request, *args, **kwargs):
    user = User.objects.get(id=kwargs['viewer_id'])
    lists = List.objects.filter(user=user, type=type)
    item = Item.objects.get(value=kwargs['viewed_id'])
    if item:
        for list in lists:
            if List.contains_item(item, list):
                list.in_list = True
            else:
                list.in_list = False

    serializer = MemberListsSerializer(lists, many=True)
    return JSONResponse(serializer.data)

# models.py
class List(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(_('list'), max_length=128)

    @classmethod
    def contains_item(cls, item, list, *args, **kwargs):
        try:
            item.lists.get(id=list.id)
            return True
        except List.DoesNotExist:
            return False

class Item(models.Model):
    lists = models.ManyToManyField(List, related_name='items')
    value = models.IntegerField(_('value'))

# serializer.py
class MemberListsSerializer(serializers.ModelSerializer):
    class Meta:
        model = List
        fields = ('id', 'user', 'name')

如果我通过 Python 调试器运行视图并在设置序列化程序变量之前检查“列表”查询集,我可以看到列表查询集中的每个元素都添加了一个“in_lists”属性。但是当我执行对 MemberListsSerializer 的调用并检查“serializer.data”时,“in_list”属性不存在。我想尝试将“in_list”添加到序列化程序类的“字段”列表中,但这不起作用,因为“in_list”不是列表模型中的字段(而且我不想将它添加到模型中这条信息并不真正属于那里)。我还研究了在对序列化程序方法的调用中添加一个额外的参数“context={'in_list': in_list}”,但这不起作用,因为它只会将“in_list”添加到返回给模板的上下文中,而不是到每个单独的列表。插入此“in_list”属性以使其被序列化程序拾取并插入其输出的正确方法是什么?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    您可以将项目传递给上下文并使用SerializerMethodField 来检查项目是否在当前列表中:

    def get_viewer_lists_checked(request, *args, **kwargs):
        ...
        item = Item.objects.get(value=kwargs['viewed_id'])
        serializer = MemberListsSerializer(lists, many=True, context={'item': item})
        return JSONResponse(serializer.data)
    
    class MemberListsSerializer(serializers.ModelSerializer):
        in_list = serializers.SerializerMethodField('get_in_list')
        class Meta:
            model = List
            fields = ('id', 'user', 'name', 'in_list')
    
        def get_in_list(self, obj):
            item = self.context['item'] 
            if List.contains_item(item, obj):
                return True
            else:
                return False 
    

    【讨论】:

    • 非常感谢!这比必须将查询集解压缩到字典中要好得多,我担心我可能不得不这样做。我修复了两个小错误。一、设置in_list时,需要为“serializers”复数。其次,需要将方法“get_in_list”作为参数传递给 SerializerMethodField。一旦我做了这两个改变,它就像一个魅力。
    • SerializerMethodField中不需要指定方法名。如果不包含,则默认为 get_<field_name>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2020-06-20
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多