簡體   English   中英

如何編寫一個django-rest-framework序列化器/字段來合並來自泛型關系的數據?

[英]How to write a django-rest-framework serializer / field to merge data from generic relations?

我有一個通用關系指向各種其他對象的對象,我需要它們合並(內聯),因此序列化對象看起來像一個完整的對象。

例如:

class Enrollement(models.Model):
    hq = models.ForeignKey(Hq)
    enrollement_date = models.Datetime()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('content_type', 'object_id')

class Nurse(models.Model):
     hospital = models.ForeignKey(Hospital)
     enrollement = GenericRelation(Enrollement)

class Pilot(models.Model):
     plane = models.ForeignKey(plane)
     enrollement = GenericRelation(Enrollement)

序列化時,我想得到這樣的東西:

{
    count: 50,
    next: 'http...',
    previous: null,
    results: [
        {
        type: "nurse",
        hq: 'http://url/to/hq-detail/view',
        enrollement_date: '2003-01-01 01:01:01',
        hospital: 'http://url/to/hospital-detail/view'

        },
        {
        type: "pilot",
        hq: 'http://url/to/hq-detail/view',
        enrollement_date: '2003-01-01 01:01:01',
        plante: 'http://url/to/plane-detail/view'

        },
    ]
}

我可以這樣做,如果可以,怎么做?

我可以嵌套一個通用關系,我可以發布處理serilizer.data以獲得我想要的東西,但我想知道是否有更好的方法。

來自未來的親朋好友:在撰寫本文時,Django REST Framework團隊似乎正在努力為通用關系添加更成熟的支持。 但它還沒有完成。 在將此答案復制粘貼到您的代碼庫之前,請首先檢查https://github.com/tomchristie/django-rest-framework/pull/755 ,看看它是否已合並到repo中。 可能有更優雅的解決方案等待着您。 - 你的古老祖先泰勒

鑒於您正在使用Django REST Framework ,如果您確實想要進行一些后處理(即使您似乎猶豫不決),您可以通過覆蓋視圖中的get_querysetlist來實現目標。 像這樣的東西:

views.py:

from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from models import *
from itertools import chain

class ResultsList(ListAPIView):
    def list(self, request, *args, **kwargs):
        nurses = Nurse.objects.all()
        pilots = Pilot.objects.all()

        results = list()
        entries = list(chain(nurses, pilots)) # combine the two querysets
        for entry in entries:
            type = entry.__class__.__name__.lower() # 'nurse', 'pilot'
            if isinstance(entry, Nurse):
                serializer = NurseSerializer(entry)
                hospital = serializer.data['hospital']
                enrollement_date = serializer.data['enrollement.date']
                hq = serializer.data['enrollement.hq']
                dictionary = {'type': type, 'hospital': hospital, 'hq': hq, 'enrollement_date': enrollement_date}
            if isinstance(entry, Pilot):
                serializer = PilotSerializer(entry)
                plane = serializer.data['plane']
                enrollement_date = serializer.data['enrollement.date']
                hq = serializer.data['enrollement.hq']
                dictionary = {'type': type, 'plane': plane, 'hq': hq, 'enrollement_date': enrollement_date}
            results.append(dictionary)
        return Response(results)

serializers.py

class EnrollementSerializer(serializer.ModelSerializer):
    class Meta:
        model = Enrollement
        fields = ('hq', 'enrollement_date')

class NurseSerializer(serializer.ModelSerializer):
    enrollement = EnrollementSerializer(source='enrollement.get')

    class Meta:
        model = Nurse
        fields = ('hospital', 'enrollement')

class PilotSerializer(serializer.ModelSerializer):
    enrollement = EnrollementSerializer(source='enrollement.get')

    class Meta:
        model = Pilot
        fields = ('plane', 'enrollement')

返回的響應看起來像:

  [
        {
              type: "nurse",
              hq: "http://url/to/hq-detail/view",
              enrollement_date: "2003-01-01 01:01:01",
              hospital: "http://url/to/hospital-detail/view"
        },
        {
              type: "pilot",
              hq: "http://url/to/hq-detail/view",
              enrollement_date: "2003-01-01 01:01:01",
              plane: "http://url/to/plane-detail/view"
        },
  ]

值得注意的是:

  • 我的serializers.py可能有點偏離,因為我對如何在序列化器中表示泛型關系的記憶有點模糊。 因人而異。
  • 與^^類似,這假設您的serializers.py已按順序排列,並且已根據您的模型正確設置其通用關系。
  • 我們在source=enrollement.get執行get ,因為否則如果我們不指定源,將返回GenericRelatedObjectManager對象。 那是因為這是一般關系所代表的。 使用.get強制查詢(如在QuerySet查詢中),該查詢訪問您設置為泛型關系源的模型(在本例中為class Enrollement(models.Model)
  • 我們必須使用list(chain())而不是| 運算符,因為查詢集來自不同的模型。 這就是為什么我們不能做entries = nurses | pilots entries = nurses | pilots
  • for entry in entries肯定會變得更加干燥。 GLHF。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM