それで、私はそれを理解しました。
URL 変数をシリアライザーに取得する
これを行うには、ModelViewSet の get_serializer_context() メソッドを上書きし、kwargs から変数を送信する必要があります。
class BrandedViewSet(viewsets.ModelViewSet):
def get_serializer_context(self):
context = super().get_serializer_context()
context['brand_slug'] = self.kwargs.get('brand_slug')
return context
次に、そのクラスですべての ModelViewSets を拡張できます。
class StateViewSet(BrandedViewSet):
queryset = State.objects.all()
serializer_class = StateSerializer
すばらしいのは、シリアライザーにこの変数を注入したとしても、 を介して HyperlinkedRelatedField クラスからもアクセスself.context
できることです。これにより、次の部分が可能になります。
追加の URL 変数を使用したカスタム ハイパーメディア リンクの構築
ドキュメントは上書きで正しかったget_url()
:
class BrandedHyperlinkMixin(object):
def get_url(self, obj, view_name, request, format):
""" Extract brand from url
"""
if hasattr(obj, 'pk') and obj.pk is None:
return None
lookup_value = getattr(obj, self.lookup_field)
kwargs = {self.lookup_url_kwarg: lookup_value}
kwargs['brand_slug'] = self.context['brand_slug']
return reverse(
view_name, kwargs=kwargs, request=request, format=format)
ただし、パート 1 で設定したコンテキストから変数を取得していることに気付くでしょう。ドキュメントが示唆するようにオブジェクトからコンテキストを取得できませんでしたが、この方法はより簡単であることが判明しました。
これが mixin である理由はurl
、関連するフィールドのハイパーリンクだけでなく、すべてのハイパーリンクで機能するようにするには、2 つのクラスを拡張する必要があるためです。
class BrandedHyperlinkedIdentityField(BrandedHyperlinkMixin,
serializers.HyperlinkedIdentityField):
pass
class BrandedHyperlinkedRelatedField(BrandedHyperlinkMixin,
serializers.HyperlinkedRelatedField):
pass
class BrandedSerializer(serializers.HyperlinkedModelSerializer):
serializer_related_field = BrandedHyperlinkedRelatedField
serializer_url_field = BrandedHyperlinkedIdentityField
これで、シリアライザーを安全に拡張でき、ハイパーリンクにブランド変数が表示されます!
class StateSerializer(BrandedSerializer):
class Meta:
model = State
fields = ('url', 'slug', 'name', 'abbrev', )