簡體   English   中英

如何在 drf-nested-routers 中包含嵌套資源的超鏈接以應用 HATEOAS 原則?

[英]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')

ERD

在此處輸入圖像描述

我想應用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屬性。

我做了一些測試並找到了解決方案。

首先,在您的案例中實現嵌套路由的最佳方法是使用這些HyperlinkedModelSerializerNestedHyperlinkedModelSerializer

所以第一層應該是這樣的:

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 以正確配置嵌套路由,更改fieldsexclude並添加 url 參數。

希望它有效!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM