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'])
谢谢你!