繁体   English   中英

序列化DRF中的相关字段

[英]Serializing related fields in DRF

我有两个模型,一个父模型和一个子模型,我希望它们存在于数据库的不同表中,但是当我返回客户端时,它们将它们表示在同一个对象(平面)上。 我已经尝试了一些选项,包括SerializerMethodFields(SMF)和ReadOnlyFields,但是它们都导致太多的数据库查询。

我还尝试过嵌套对象,然后稍后对其进行展平,这确实起作用,但是由于Django的序列化程序的工作方式,导致了更多的代码。 这让我感到应该有一种更好的方法来完成此任务。

这是使用SMF方法调用串行器的示例:

# in the view
class ListFoo(APIView):
    def get(self, request):
        foo = Foo.objects.prefetch_related('bar').all()
        serializer = FooSerializer(foo, may=True)
        Response(serializer.data, status=status.HTTP_200_OK)

# in the serializer
class FooSerializer(ModelSerializer):
    employer = SerializerMethodField()
    position = SerializerMethodField()

    class Meta:
        model = Foo
        fields('id', 'name', 'employer', 'position')

    def get_employer(self, foo):
        # use related manager to access related object
        return foo.bar.last().employer

    def get_position(self, foo):
        # use related manager to access related object
        return foo.bar.last().position

# in the models
class Foo(models.Model):
    name = models.CharField(max_length=150)

class Bar(models.Model):
    employer = models.CharField(max_length=150)
    position = models.CharField(max_length=150)
    foo = models.ForeignKey(
        Foo,
        related_name='bar',
        unique=False,
        on_delete=models.CASCADE
    )

现在上面的代码可以工作了,但是如果我要查询许多Foo对象,它将查询+1 bar我需要从bar访问的每个属性。 我正在尝试找到一种方法来对序列化程序进行初始化时可能查询的数据进行全局存储/缓存。

对更有效或更有效的方法有什么想法吗?

更新:我基本上已经弄清楚了,明天将发布解决方案。 我不知道有多少种方法可以对使用预取创建的查询集进行不正确的操作。

上面的代码的问题是,当我使用最后一种方法对queryset进行操作时

def get_employer(self, foo):
    # use related manager to access related object
    return foo.bar.last().employer

每次调用get_employer ,Django都会查询数据库。 阅读文档其他几个答案之后 ,我意识到使用all()方法是下一步的重要步骤,因为它将返回相关对象的查询集(在视图中预先提供)。 对我来说很奇怪,您不能像通常使用last()filter()这样的方法直接对相关对象进行操作,但是可以对其进行迭代和过滤。

解决我的问题所需要做的就是返回related_manager的queryset中的最后一个项目,我通过使用下标返回queryset中的最后一个对象来实现这一点。 我敢肯定,有一些方法可以减少代码,但是可以。

def get_employer(self, foo):
    qs = foo.bar.all()
    last = query.count()
    obj = model_to_dict(qs[last-1])

    return obj.get('employer')

不太清楚,我了解,但您似乎想要Foo对象的最后一位雇主。 因此,您的SerializerMethodField可能如下所示(假设此处的创建日期降序反映了您的最新雇主)

def get_employer(self, foo):
   obj= foo.bar.all().order_by('-created')[0]
   return obj.employer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM