[英]How to include Hyperlinks for nested resources in drf-nested-routers to apply HATEOAS principle?
我在 Django REST 框架中有一個 API,其中包含以下嵌套資源
/wizard-api/industries/
/wizard-api/industries/<pk>/
/wizard-api/industries/<industry_pk>/sub-industries/
/wizard-api/industries/<industry_pk>/sub-industries/<pk>/
/wizard-api/industries/<industry_pk>/sub-industries/<sub_industry_pk>/details/
/wizard-api/industries/<industry_pk>/sub-industries/<sub_industry_pk>/details/<pk>/
# basenames:
wizard-api:industries-list
wizard-api:industries-detail
wizard-api:sub-industries-list
wizard-api:sub-industries-detail
wizard-api:details-list
wizard-api:details-detail
這里我的 URLs 使用drf-nested-routers配置:
# Nested Routes
first_level = routers.SimpleRouter()
first_level.register(r'industries', views.IndustryViewSet, basename='industries')
second_level = routers.NestedSimpleRouter(first_level, r'industries', lookup='industry')
second_level.register(r'sub-industries', views.SubIndustryViewSet, basename='sub-industries')
third_level = routers.NestedSimpleRouter(second_level, r'sub-industries', lookup='sub_industry')
third_level.register(r'details', views.SubIndustryDetailsViewSet, basename='abc')
我想應用HATEOAS原則
# endpoint: /wizard-api/industries/1/
# response:
{
"id": 1,
"name": "food and beverage",
"subindustries": "http://127.0.0.1:8000/wizard-api/industries/1/sub-industries/"
}
我在第一個 Serializer 中使用HyperlinkedIdentityField完成了第一級
class IndustryModelSerializer(serializers.ModelSerializer):
subindustries = serializers.HyperlinkedIdentityField(
view_name='wizard-api:sub-industries-list',
lookup_url_kwarg='industry_pk'
)
class Meta:
model = Industry
exclude = ['created', 'modified', 'active']
當我嘗試在后續級別應用相同的邏輯時出現問題,即:從子行業級別生成 url 到詳細信息級別:
/wizard-api/industries/<industry_pk>/sub-industries/<sub_industry_pk>/details/
我嘗試了二級(子行業)序列化程序中的詳細信息字段:
class SubIndustryModelSerializer(serializers.ModelSerializer):
details = serializers.HyperlinkedIdentityField(
view_name='wizard-api:details-list',
lookup_url_kwarg='industry_pk'
)
class Meta:
model = SubIndustry
exclude = ['created', 'modified', 'active']
預期的響應是:
# endpoint: /wizard-api/industries/1/sub-industries/
# response:
[
{
"id": 1,
"name": "beverage industries",
"details": "http://127.0.0.1:8000/wizard-api/industries/1/sub-industries/1/details/"
},
{
"id": 2,
"name": "food production",
"details": "http://127.0.0.1:8000/wizard-api/industries/1/sub-industries/2/details/"
}
]
但我收到以下錯誤:
無法使用視圖名稱“wizard-api:details-list”解析超鏈接關系的 URL。 您可能未能在 API 中包含相關模型,或者在該字段上錯誤地配置了
lookup_field
屬性。
我做了一些測試並找到了解決方案。
首先,在您的案例中實現嵌套路由的最佳方法是使用這些HyperlinkedModelSerializer 、 NestedHyperlinkedModelSerializer 。
所以第一層應該是這樣的:
class IndustryModelSerializer(HyperlinkedModelSerializer):
subindustries = serializers.HyperlinkedIdentityField(
view_name='wizard-api:sub-industries-list',
lookup_url_kwarg='industry_pk'
)
class Meta:
model = Industry
fields = ['subindustries', 'foo'...]
第二級的主要問題可以這樣解決:
class SubIndustryModelSerializer(NestedHyperlinkedModelSerializer):
parent_lookup_kwargs = {
'industry_pk': 'industry_id'
}
class Meta:
model = SubIndustry
fields = ['foo', 'url', ...]
extra_kwargs = {
'url': {
'view_name': 'wizard-api:details-list',
'lookup_url_kwarg': 'sub_industry_pk'
}
}
根據您的 ERD,您必須包含 parent_kwargs 以正確配置嵌套路由,更改fields的exclude並添加 url 參數。
希望它有效!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.