1

Django 世界的新手。我正在努力为嵌套路由创建超链接。

我得到的错误是:

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

一些项目设置说明

  • 使用 django rest 框架

  • 用于DRF-extensions创建路线

  • 使用模型视图集

  • 预期终点:

    • /帐户/

    • /accounts/<pk>/

    • /accounts/<pk>/campaigns/

    • /accounts/<pk>/campaigns/<pk>/

    • /accounts/<pk>/campaigns/adgroup/

    • /accounts/<pk>/campaigns/adgroup/<pk>/

  • rest在 urls.py 中设置命名空间

  • 用于HyperlinkedIdentityField创建超链接。它仅适用于父对象,即

    • url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')

然而,任何嵌套对象都会失败,即

  • url = serializers.HyperlinkedIdentityField(view_name='rest:campaign-detail')

该模型非常简单,一个Account可以有多个Campaigns,一个 Campaign 可以有多个AdGroups。请参见下面的代码:

模型.py

from django.db import models
from django.db.models import Q
from model_utils import Choices

ORDER_COLUMN_CHOICES = Choices(
    ('0', 'id'),
    ('1', 'keyword'),
    ('2', 'status'),
    ('3', 'match_type'),
)


# Account
class Account(models.Model):
    account_name = models.CharField(max_length=128)

    def __str__(self):
        return self.account_name


# Campaign
class Campaign(models.Model):
    class Status(models.TextChoices):
        Enabled = "Enabled"
        Paused = "Paused"

    account = models.ForeignKey(
        to=Account, on_delete=models.CASCADE, related_name='campaigns'
    )
    campaign_name = models.CharField(max_length=128)
    status = models.CharField(max_length=21, choices=Status.choices, default=Status.Paused)

    def __str__(self):
        return self.campaign_name


# AdGroup
class AdGroup(models.Model):
    class Status(models.TextChoices):
        Enabled = "Enabled"
        Paused = "Paused"

    campaign = models.ForeignKey(
        to=Campaign, on_delete=models.CASCADE, related_name='adgroups'
    )
    adgroup_name = models.CharField(max_length=128)
    status = models.CharField(max_length=21, choices=Status.choices, default=Status.Enabled)

    def __str__(self):
        return self.adgroup_name

视图.py

from rest_framework import viewsets
from .serializers import *
from . import models
from rest_framework_extensions.mixins import NestedViewSetMixin


class AccountViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
    serializer_class = AccountSerializer
    queryset = models.Account.objects.all()


class CampaignViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
    serializer_class = CampaignSerializer
    queryset = models.Campaign.objects.all()


class AdGroupViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
    serializer_class = AdGroupSerializer
    queryset = models.AdGroup.objects.all()

序列化程序.py

from rest_framework import serializers
from . import models


class CampaignSerializer(serializers.ModelSerializer):

    url = serializers.HyperlinkedIdentityField(view_name="rest:campaign-detail")

    class Meta:
        model = models.Campaign
        fields = '__all__'


class AccountSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')

    class Meta:
        model = models.Account
        fields = '__all__'


class AdGroupSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='rest:adgroup-detail')

    class Meta:
        model = models.AdGroup
        fields = '__all__'


我有 2 个 URL 文件。该项目名为Vanilla , DRF 逻辑所在的应用程序名为rest 。

香草 urls.py

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('', include('rest.urls', namespace='rest')),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    path('admin/', admin.site.urls)
]

休息网址.py

from django.urls import include, path
from . import views
from rest_framework_extensions.routers import ExtendedSimpleRouter

app_name = 'rest'

router = ExtendedSimpleRouter()
(
    router.register(r'accounts',
                    views.AccountViewSet,
                    basename='account')

    .register(r'campaigns',
              views.CampaignViewSet,
              basename='campaign',
              parents_query_lookups=['account__id'])

    .register(r'adgroups',
              views.AdGroupViewSet,
              basename='adgroup',
              parents_query_lookups=['campaign__account', 'campaign'])

谢谢你!

4

1 回答 1

0

在所有相关的序列化程序中使用 hyperlinkedModelSerializer。那应该工作

于 2021-09-21T10:11:01.477 回答