首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将嵌套资源的超链接包含在drf-嵌套路由器中,以应用HATEOAS原理?

如何将嵌套资源的超链接包含在drf-嵌套路由器中,以应用HATEOAS原理?
EN

Stack Overflow用户
提问于 2022-06-01 20:46:54
回答 1查看 90关注 0票数 2

上下文

我在Django REST框架中有一个API,它有以下嵌套资源

代码语言:javascript
复制
/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

这里我的URL配置使用drf-nested-routers

代码语言:javascript
复制
# 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

我想应用原理

代码语言:javascript
复制
# 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实现了第一个级别。

代码语言:javascript
复制
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到详细信息级别时,就会出现问题。

代码语言:javascript
复制
/wizard-api/industries/<industry_pk>/sub-industries/<sub_industry_pk>/details/

我尝试使用第二级(子行业)序列化程序中的details字段:

代码语言:javascript
复制
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']

期望的

预期的反应是:

代码语言:javascript
复制
# 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/"
    }
]

错误

但我得到了以下错误:

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-21 20:39:22

我做了一些测试并找到了解决办法。

首先,在您的情况下实现嵌套路由的最佳方法是使用以下HyperlinkedModelSerializerNestedHyperlinkedModelSerializer.

所以第一个层次应该是这样的:

代码语言:javascript
复制
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'...]

第二层的主要问题可以这样解决:

代码语言:javascript
复制
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,更改字段的排除,并添加url参数。

希望它能成功!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72467862

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档