序列化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 访问的每个属性。我正在尝试找到一种在全局化存储/缓存数据的方式,当序列化程序初始化时,我可能会查询该数据。


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


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


陪伴而非守候
浏览 180回答 2
2回答

茅侃侃

不太确定,我明白,但看起来你想要你的 Foo 对象的最后一个雇主。那么你的 SerializerMethodField 可能如下(假设这里创建日期降序反映了你最近的雇主)def get_employer(self, foo):   obj= foo.bar.all().order_by('-created')[0]   return obj.employer

慕桂英546537

上面的代码的问题是,当我使用最后一种方法对queryset进行操作时def get_employer(self, foo):    # use related manager to access related object    return foo.bar.last().employer每次get_employer调用时,Django 都会查询数据库。阅读文档和其他几个答案后,我意识到使用该all()方法是重要的下一步,因为它将返回相关对象的查询集(在视图中预取)。令我感到奇怪的是,您不能像通常使用类似last()or的方法那样直接对相关对象进行操作,filter()但您可以遍历它们并进行过滤。解决我的问题所需要做的就是返回 related_manager 查询集中的最后一项,我通过使用下标返回查询集中的最后一个对象来完成此操作。我敢肯定,有一些方法可以减少代码,但是它可以工作。def get_employer(self, foo):    qs = foo.bar.all()    last = query.count()    obj = model_to_dict(qs[last-1])    return obj.get('employer')
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python