为什么 Django REST Framework 的 HyperlinkedModelSerializer 不能形成 URL?

Bez*_*ewy 2 django django-rest-framework

DRF 的新手,只要我不在字段中包含“url”,一切都可以正常工作。这是我所拥有的:

序列化器:

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Task
        fields = ('pk', 'short_desc', 'scheduled_date')
Run Code Online (Sandbox Code Playgroud)

视图集:

class TaskViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Task.objects.all().order_by('scheduled_date')
    serializer_class = TaskSerializer
Run Code Online (Sandbox Code Playgroud)

网址:

router = routers.DefaultRouter()
router.register(r'tasks', views.TaskViewSet)

urlpatterns = [

    [... bunch of non-REST URLs]

    # REST API
    url(r'^', include(router.urls)),
Run Code Online (Sandbox Code Playgroud)

在运行时,打印 router.urls 给我:

<RegexURLPattern api-root ^$>
<RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>
<RegexURLPattern task-list ^tasks/$>
<RegexURLPattern task-list ^tasks\.(?P<format>[a-z0-9]+)/?$>
<RegexURLPattern task-detail ^tasks/(?P<pk>[^/.]+)/$>
<RegexURLPattern task-detail ^tasks/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>
Run Code Online (Sandbox Code Playgroud)

无论 [...]/tasks/和[...]/tasks/123/工作,如果我键入他们到我的浏览器,这使我相信,任务列表和任务详细视图做,事实上是存在的。

现在我通过向序列化程序添加“url”来引入一个问题:

class TaskSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Task
        fields = ('url', 'pk', 'short_desc', 'scheduled_date')
Run Code Online (Sandbox Code Playgroud)

将“url”添加到字段后,出现以下错误:

无法使用视图名称“任务详细信息”解析超链接关系的 URL。您可能没有在 API 中包含相关模型,或者错误地配置了lookup_field该字段的属性。

DRF 文档说:

需要有一种方法来确定应该使用哪些视图来超链接到模型实例。默认情况下,超链接应对应于与样式“{model_name}-detail”匹配的视图名称,并通过 pk 关键字参数查找实例。

由于我已经验证了 task-detail 存在并且相应的 URL[...]/tasks/123/有效,我终生无法弄清楚为什么 DRF 不能形成 URL。有任何想法吗?

Bez*_*ewy 6

受 Kunkka 的回答所揭示的线索的启发,我有一个如下所示的解决方案:

class TaskSerializer(serializers.HyperlinkedModelSerializer):

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

    class Meta:
        model = Task
        fields = ('url', 'pk', 'short_desc', 'scheduled_date')
Run Code Online (Sandbox Code Playgroud)

即我在url = [...]最初在我的问题中发布的序列化程序中添加了一行。这解决了可能由 DRF 不知道“task-detail”实际上在“task”命名空间中引起的查找问题。

有什么更好的解决方案吗?