所以,我想通了。
将 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
然后,您可以使用该类扩展所有 ModelViewSet:
class StateViewSet(BrandedViewSet):
queryset = State.objects.all()
serializer_class = StateSerializer
很好的是,即使您已经使用此变量注入了 Serializer,它也可以从 HyperlinkedRelatedField 类通过 via 访问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
超链接,而不仅仅是相关的字段超链接。
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', )