Переход к использованию маршрутизатора URL вызывает исключение ImproperlyConfigured
Я работал над учебником по Django Rest Framework и на самом последнем шаге я столкнулся с ошибкой:
Тип исключения: ImproperlyConfigured.
Значение исключения:
Не удалось разрешить URL для отношения с гиперссылкой, используя имя представления "snippet-detail". Возможно, вы не включили связанную модель в свой API или неправильно настроили атрибут lookup_field для этого поля.
При попытке просмотра /settings/ или /users/ (посещение любых страниц пользователей дает то же исключение, но с "user-detail" вместо "snippet-detail"), а также любых конкретных индексов из них и т.д. Работает только root и login.
Весь мой код до сих пор работал нормально, и я очень озадачен тем, почему копирование-вставка из учебника привела к таким катастрофическим результатам
Сравнивая свои файлы сниппетов с файлами, доступными в репозитории учебника , я не смог найти существенной разницы (все, что я нашел, это несоответствия в пробельных символах). Тем не менее, вот код, который я использую
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')),
]
Роутеру передавались неправильные базовые имена (множественные формы snippet и user, а не единственные). Спасибо @IainShelvington за ответ в комментариях!