我在API网址的基础上使用了一个变量,与Django REST Framework the docs中的设置相同:
/api/<brand>/states/<state_pk>/
基础品牌slug之后的所有内容都是标准的API格式,因此我使用ModelViewSets为我的对象生成所有列表和详细信息视图。 API中的所有内容都由品牌过滤,因此这种设置很有意义。
简化项目/ urls.py
urlpatterns = patterns(
'',
url(r'^v2/(?P<brand_slug>\w+)/', include(router.urls, namespace='v2')),
)
简化的api / urls.py
router = routers.DefaultRouter()
router.register(r'states', StateViewSet)
router.register(r'cities', CityViewSet)
我还需要所有型号的超媒体链接,这就是我遇到问题的地方。 REST框架不知道如何获取此品牌变量并使用它来生成正确的链接。通过遵循文档尝试解决这个问题让我有两个挫折:
这里缺少什么元素?
答案 0 :(得分:2)
所以,我明白了。
要执行此操作,您需要覆盖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
有什么好处的,即使你已经为这个变量注入了Serializer,它也可以通过self.context
从HyperlinkedRelatedField类访问,这就是下一部分可能的方式。
文档在覆盖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', )