簡體   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