如何在drf-nested-routers中包括嵌套资源的超链接以应用Hateoas原理?

发布于 2025-02-03 16:16:21 字数 3245 浏览 4 评论 0原文

上下文

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

,我的URL使用 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/"
}

中实现了第一级,

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']

我使用 hyper -hyprinbedidentityfieldfield 在第一个序列化器问题

当我尝试在后续级别应用相同的逻辑时出现问题,即:从子工业级别 详细信息级别

/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 该字段上的属性。

Context

I have an API in Django REST framework with the following nested resources

/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

Here my URLs config using 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

enter image description here

I want to apply the HATEOAS principle

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

I made it for the first level using the HyperlinkedIdentityField in the first Serializer

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']

Problem

The problem appears when I try to apply the same logic in the subsequent levels, i.e: generating the url from the sub-industries level to the details level:

/wizard-api/industries/<industry_pk>/sub-industries/<sub_industry_pk>/details/

I tried with the details field in the serializer of the second level (sub-industries):

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']

Expected

The expected response is:

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

Error

But I got the following error:

Could not resolve URL for hyperlinked relationship using view name
"wizard-api:details-list". You may have failed to include the related
model in your API, or incorrectly configured the lookup_field
attribute on this field.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若沐 2025-02-10 16:16:21

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

首先,在您的情况下,实现嵌套路线的最佳方法是使用这些超链接式modelializer nestedhyhyperlinkedmodelserialializer

因此,第一个级别应该看起来像这样:

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,以适当地配置嵌套路由,更改 dubl 对于字段,并添加URL参数。

希望它有效!

I made some tests and found the solution.

First, the best way to implement the nested routes in your case will be with these HyperlinkedModelSerializer, NestedHyperlinkedModelSerializer.

So the first level should look like this:

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'...]

The main problem in the second level can be fixed like this:

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'
            }
        }

Based on your ERD, you must include a parent_kwargs for the proper configuration of nested routes, change the exclude for fields, and add the url parameter.

Hope it works!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文