シリアライザ間の依存関係を作成することはできますか?シリアライザの結果を別のシリアライザのクエリーセットとして使用する方法
私がしたいことは、Fooのクエリーセットを選択したエンティティのクエリーセットに限定することです。それを行う方法はありますか?
シリアライザ間の依存関係を作成することはできますか?シリアライザの結果を別のシリアライザのクエリーセットとして使用する方法
私がしたいことは、Fooのクエリーセットを選択したエンティティのクエリーセットに限定することです。それを行う方法はありますか?
Djangoの残りのフレームワークは、少なくともバージョン2.xに、これは簡単なことはない - と私は/私は、これは中に固定ハッキングバージョンではそれを改善するために任意の計画3.
があったされているかどうかわかりませんシリアライザ内のtryキャッチを持つさまざまな場所で、問題を標準化しようとする前に、データ・ディクショナリに渡された親プロパティによって該当するフィールドのクエリーセットがフィルタリングされます。
SlugRelatedDependentField
class SlugRelatedDependentField(SlugRelatedField):
def __init__(self, depends_on=None, **kwargs):
assert depends_on is not None, 'The `depends_on` argument is required.'
self.depends_on = depends_on # archive_unit__organization or organization
self.depends_segments = self.depends_on.split('__')
self.depends_parent = self.depends_segments.pop(0)
self.depends_field = SimpleLazyObject(lambda: self.parent.parent.fields[self.depends_parent])
self.depends_queryset = SimpleLazyObject(lambda: self.depends_field.queryset)
self.depends_model = SimpleLazyObject(lambda: self.depends_queryset.model)
super(SlugRelatedDependentField, self).__init__(**kwargs)
def contextualize(self, instance, data):
self.data = data
self.instance = instance
def get_queryset(self):
try:
return self.queryset.filter(**{self.depends_on: reduce(getattr, self.depends_segments, self.get_relation())})
except self.depends_model.DoesNotExist:
# if parent was absent or invalid, empty the queryset
return self.queryset.none()
except TypeError:
# if parent was a Page instance, use the full queryset, it's only a list view
return self.queryset.all()
def get_relation(self):
try:
# if an allowed parent was passed, filter by it
return self.depends_queryset.get(**{self.depends_field.slug_field: self.data[self.depends_parent]})
except (KeyError, TypeError):
# if data was empty or no parent was passed, try and grab it off of the model instance
if isinstance(self.instance, self.parent.parent.Meta.model):
return getattr(self.instance, self.depends_parent)
elif self.instance is None:
raise self.depends_model.DoesNotExist
else:
raise TypeError
使用
class RepositorySerializer(ModelSerializer):
organization = SlugRelatedField(queryset=Organization.objects.all(), slug_field='slug')
teams = SlugRelatedDependentField(allow_null=True, depends_on='organization', many=True, queryset=Team.objects.all(), required=False, slug_field='slug')
def __init__(self, instance=None, data=empty, **kwargs):
f = self.fields['teams']
# assign instance and data for get_queryset
f.child_relation.contextualize(instance, data)
# inject relation values from instance if they were omitted so they are validated regardless
if data is not empty and instance and name not in data:
data[name] = [getattr(relation, f.child_relation.slug_field) for relation in getattr(instance, name).all()]
super(RepositorySerializer, self).__init__(instance=instance, data=data, **kwargs)
概要
SlugRelatedDependentField
はを受け入れるために定期的SlugRelatedField
を拡張しますkwargは、フィールドの他のフィールドとの関係を表す文字列を受け入れます。この例では、このレポジトリに割り当てられたチームが組織に属していなければならないと説明しています。親が存在しない場合、私は.none()
でクエリセットを空にする
いくつかの落とし穴
OPTIIONS
要求と検証メッセージを介して公開することができる選択肢漏れを回避し、通常は望ましくありません。data
を使用しました。これは、親フィールドのオブジェクトが一致していない可能性がありますが、data
が一貫して使用できるためです。 PATCH
リクエストの場合PATCH
リクエスト内のレコードのorganization
を変更した場合、割り当て済みのteams
は適用されなくなりました。遠い関係のサポート
このソリューションは、のために食料調達するもう一つの問題は、遠い関係を参照している、これはdepends_on
例えばに__
区切られた文字列を渡すことで行うことができますrepository__organization
、私はこれのための素晴らしい例のユースケースを持っていませんが、それが必要な場合はそこにあります。