转换为使用 URL 路由器导致 ImproperlyConfigured 异常
Converting to using URL router is causing a ImproperlyConfigured exception
我一直在学习 Django Rest Framework 教程和 very last step 我遇到错误:
Exception Type: ImproperlyConfigured.
Exception Value:
Could not resolve URL for hyperlinked relationship using view name "snippet-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.
当试图查看 /settings/ 或 /users/ 时(访问任何用户页面都会产生相同的异常,但用“user-detail”代替“snippet-detail”)以及它们的任何特定索引等等。所有的工作都是root和登录。
到目前为止我的所有代码都运行良好,我很困惑为什么从教程中复制粘贴会产生如此灾难性的结果
在将我的代码片段文件与 tutorial's repo 上可用的代码片段文件进行比较时,我没有发现任何显着差异(我发现的只是空格中的不一致)。话虽如此,这是我正在使用的代码。
snippets/views.py:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics, permissions
from django.contrib.auth.models import User
from snippets.permissions import IsOwnerOrReadOnly
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import renderers
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
This viewset automatically provides `list` and `retrieve` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
class SnippetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
snippets/urls.py:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippets")
router.register(r'users', views.UserViewSet,basename="users")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
snippets/serializers.py:
from django.contrib.auth.models import User
from rest_framework import serializers
from snippets.models import Snippet
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(
view_name='snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code',
'linenos', 'language', 'style')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(
many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
tutorial/urls.py:
"""tutorial URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('snippets.urls')),
]
urlpatterns += [
path('api-auth/', include('rest_framework.urls')),
]
路由器被传递了错误的基本名称(片段和用户的复数形式而不是单数形式)。感谢@IainShelvington 在评论中的回答!
详细说明:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippets")
router.register(r'users', views.UserViewSet,basename="users")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
应该是
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippet")
router.register(r'users', views.UserViewSet,basename="user")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
我一直在学习 Django Rest Framework 教程和 very last step 我遇到错误:
Exception Type: ImproperlyConfigured.
Exception Value:
Could not resolve URL for hyperlinked relationship using view name "snippet-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.
当试图查看 /settings/ 或 /users/ 时(访问任何用户页面都会产生相同的异常,但用“user-detail”代替“snippet-detail”)以及它们的任何特定索引等等。所有的工作都是root和登录。
到目前为止我的所有代码都运行良好,我很困惑为什么从教程中复制粘贴会产生如此灾难性的结果
在将我的代码片段文件与 tutorial's repo 上可用的代码片段文件进行比较时,我没有发现任何显着差异(我发现的只是空格中的不一致)。话虽如此,这是我正在使用的代码。
snippets/views.py:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics, permissions
from django.contrib.auth.models import User
from snippets.permissions import IsOwnerOrReadOnly
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import renderers
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
This viewset automatically provides `list` and `retrieve` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
class SnippetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
snippets/urls.py:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippets")
router.register(r'users', views.UserViewSet,basename="users")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
snippets/serializers.py:
from django.contrib.auth.models import User
from rest_framework import serializers
from snippets.models import Snippet
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(
view_name='snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code',
'linenos', 'language', 'style')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(
many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
tutorial/urls.py:
"""tutorial URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('snippets.urls')),
]
urlpatterns += [
path('api-auth/', include('rest_framework.urls')),
]
路由器被传递了错误的基本名称(片段和用户的复数形式而不是单数形式)。感谢@IainShelvington 在评论中的回答!
详细说明:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippets")
router.register(r'users', views.UserViewSet,basename="users")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
应该是
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename="snippet")
router.register(r'users', views.UserViewSet,basename="user")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]