Не удалось разрешить 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 во всех ваших связанных сериализаторах. это должно сработать