web-dev-qa-db-ja.com

ネストされたシリアライザーとして無関係なモデルからクエリセットをシリアル化する方法は?

外部キーではなく、親モデルのいくつかの基準に基づいて、ネストされたシリアライザーを既存のシリアライザーに追加しようとしています。ユースケースは、Postgres ArrayFieldでフィルタリングすることによって識別される「ResearchTemplate」オブジェクトの配列を持つ「Research」オブジェクトを返すことです。

モデル

 
 class Research(TimeStampedModel):
 category = models.CharField(max_length = 100、choices = RESEARCH_TEMPLATE_CATEGORIES、default = 'quote')
 body = models。 CharField(max_length = 1000、blank = True、default = '')#ナゲットを構成するテキストの本文
 additionaldata = JSONField(null = True)#ラッパーにマージされるすべての可変値
 
 def __str __(self):
 return self.body 
 
 class Meta:
 ordering =( 'created'、)
 
 class ResearchTemplate(TimeStampedModel):
 template = models.TextField(blank = True、default = '')
 category = models.CharField(max_length = 100、choices = RESEARCH_TEMPLATE_CATEGORIES、default = 'quote')
 mergefields = ArrayField(models.CharField(max_length = 200)、blank = True)
 
 def save(self、* args、* * kwargs):
 merges = re.findall( "{{(。*?)}}"、self.template)#口ひげ内からすべてのテンプレート名を取得します
 self.mergefields = list(set(merges))#TODO:一意にする
 super(TimeStampedModel、self).save(* args、** kwargs)
 
 def __str __(self):
 return self.wrapper 
 
 class Meta:
 ordering =( 'created'、)
 

シリアライザ

 
 class ResearchSerializer(serializers.ModelSerializer):
 templates = ResearchTemplateSerializer(many = True)
 
 class Meta:
 model = Research 
 fields =( 'id'、 'created'、 'speaker'、 'body'、 'templates')
 
 class ResearchTemplateSerializer(serializers.RelatedField):
 def get_queryset(self、values):
 return ResearchTemplate.objects.filter(mergefields__contained_by = ['Django'])#これは、ResearchオブジェクトのJSONフィールドからのキーの配列でなければなりません
 
 class Meta:
 model = ResearchTemplate 
 fields =( 'id'、 'template')
 

それらをマッピングする外部キーがあるときにシリアライザーをネストすることができましたが、カスタムクエリセットではそうすることができません。おそらく私はこれについて適切に考えていません。リサーチモデルに何らかの形の「関係」フィールドが必要です。

親モデルから指定された値を持つフィルターから返されるすべての行のシリアル化されたリストをネストするにはどうすればよいですか?

15
Henry Goddard

DRFの SerializerMethodField を使用できます。

ResearchTemplateSerializerRelatedFieldではなく、通常のModelSerializerとして定義します。

次に、ResearchSerializerを次のように置き換えます。

class ResearchSerializer(serializers.ModelSerializer):
    templates = serializers.SerializerMethodField()

    class Meta:
        model = Research
        fields = ('id', 'created', 'speaker', 'body', 'templates')

    def get_templates(self, obj):
        values = obj.get_values() # whatever your filter values are. obj is the Research instance
        templates = ResearchTemplate.objects.filter(mergefields__contained_by=values) # Or whatever queryset filter
        return ResearchTemplateSerializer(templates, many=True).data
27
ChidG