Не удалось разрешить URL для отношений с гиперссылками, используя имя представления "rest:campaign-detail".

Новичок в мире 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.

Некоторые замечания по настройке проекта

  • используя DRF-extensions для создания маршрутов

  • использование ModelViewSet

  • Предполагаемые конечные точки:

    • https://.../accounts/

    • https://.../accounts/< pk >/

    • https://.../accounts/< pk >/campaigns/

    • https://.../accounts/< pk >/campaigns/

    • https://.../accounts/< pk >/campaigns/adgroup/

    • https://.../accounts/< pk >/campaigns/adgroup/< pk >

  • Установите пространство имен rest в urls.py

    .
  • Используем HyperlinkedIdentityField для создания гиперссылки. Это работает только с родительским объектом, т.е.

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

Однако не работает с любым вложенным объектом, т.е.

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

Модель очень проста, Account может иметь множество Campaigns, а кампания может иметь множество AdGroups. Смотрите код ниже:

models.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

views.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()

serializers.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 и приложение под названием rest, где сидит логика DRF.

Vanilla 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)
]

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

Спасибо!

используйте hyperlinkedModelSerializer во всех ваших связанных сериализаторах. это должно сработать

Вернуться на верх