【问题标题】:How to include Hyperlinks for nested resources in drf-nested-routers to apply HATEOAS principle?如何在 drf-nested-routers 中包含嵌套资源的超链接以应用 HATEOAS 原则?
【发布时间】:2022-06-22 04:39:22
【问题描述】:

上下文

我在 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

这是我使用 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/"
}

我在第一个序列化器中使用 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']

问题

当我尝试在后续级别应用相同的逻辑时出现问题,即:从sub-industries级别生成url到details级别

/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/"
    }
]

错误

但我收到以下错误:

无法使用视图名称解析超链接关系的 URL “向导-api:详细信息列表”。您可能没有包含相关的 您的 API 中的模型,或者错误地配置了 lookup_field 该字段的属性。

【问题讨论】:

    标签: python-3.x django-rest-framework hyperlink hateoas drf-nested-routers


    【解决方案1】:

    我做了一些测试并找到了解决方案。

    首先,在您的案例中实现嵌套路由的最佳方式是使用这些库 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 参数。

    希望它有效!

    【讨论】:

      猜你喜欢
      • 2021-04-18
      • 2018-03-11
      • 2020-11-15
      • 2014-04-07
      • 2019-08-07
      • 1970-01-01
      • 2015-11-24
      • 2023-03-29
      • 2015-01-10
      相关资源
      最近更新 更多