当覆盖 get_queryset 时,DRF 抛出 django.core.exceptions.ImproperlyConfigured

Age*_*aun 5 python django django-rest-framework

Django Rest 框架抛出:

\n\n
\n

django.core.exceptions.ImproperlyConfigured:无法使用视图名称“customuser-detail”解析超链接关系的 URL。您可能未能在 API 中包含相关模型,或者错误配置了lookup_field该字段的属性。

\n
\n\n

当我尝试覆盖 get_queryset时时。\n我的用户序列化器:

\n\n
\nclass UserSerializer(serializers.HyperlinkedModelSerializer):\n    """\n    Represent User Serializer class.\n    """\n    teacher_account = TeacherSerializer(required=False)\n    student_account = StudentSerializer(required=False)\n\n    account_type = serializers.IntegerField(required=True)\n\n    class Meta:\n        model = CustomUser\n        fields = [\'url\', \'username\', "password", \'email\', \'first_name\', \'last_name\', "account_type", \'teacher_account\', \'student_account\']\n\n        email_validator = UniqueValidator(queryset=CustomUser.objects.all(), message="A user with that email already exists.")\n\n        extra_kwargs = {\n            "password": {"write_only": True},\n            "email": {"required": True, "validators": [email_validator]}\n        }\n\n    @staticmethod\n    def setup_eager_loading(queryset):\n        queryset = queryset.select_related(\'teacher_account\', \'student_account\')\n        return queryset\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

用户/模型.py:

\n\n
class StudentAccount(models.Model):\n    """\n    Represent student\'s account model.\n\n    """\n    classes = models.ManyToManyField(\'classroom.Class\', related_name="students")\n\n\nclass TeacherAccount(models.Model):\n    """\n    Represent teacher\'s account.\n\n    use get_subject_name from {root}/utils.py for get name of the subject.\n    """\n\n    subject_id = models.PositiveSmallIntegerField("\xd0\x9f\xd1\x80\xd0\xb5\xd0\xb4\xd0\xbc\xd0\xb5\xd1\x82", choices=SUBJECTS_CHOICES, blank=False, default=0)\n\n\nclass CustomUser(AbstractUser):\n    """\n    Represent Custom user model, inherited from AbstractUser\n\n    account_type = 0(teacher) or 1(student)\n    """\n    student_account = models.OneToOneField(StudentAccount, on_delete=models.CASCADE, blank=True, null=True, related_name="user")\n    teacher_account = models.OneToOneField(TeacherAccount, on_delete=models.CASCADE, blank=True, null=True, related_name="user")\n\n    account_type = models.PositiveSmallIntegerField(default=1)\n\n    first_name = models.CharField("-", max_length=30, blank=False)\n    last_name = models.CharField("-", max_length=150, blank=False)\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的观点.py:

\n\n
class UserViewSet(viewsets.ModelViewSet):\n    """\n    API endpoint that allows users to be viewed or edited.\n    """\n\n    permission_classes = (permissions.AllowAny,)\n    # queryset = CustomUser.objects.all()\n    # queryset_raw = CustomUser.objects.all()\n    # queryset = UserSerializer.setup_eager_loading(queryset_raw)\n    model = CustomUser\n    serializer_class = UserSerializer\n\n    def get_queryset(self):\n        queryset = CustomUser.objects.all()\n        # queryset = self.get_serializer_class().setup_eager_loading(queryset)\n        return queryset\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的网址.py:

\n\n
from django.urls import path, include\n\nfrom rest_framework import routers\nfrom knox import views as knox_views\n\nfrom .views import UserViewSet, ClassViewSet, LoginView, LessonViewSet\n\nrouter = routers.DefaultRouter()\nrouter.register(\'users\', UserViewSet, basename="CustomUser")\nrouter.register(\'classes\', ClassViewSet)\nrouter.register(\'lessons\', LessonViewSet)\n\n\nurlpatterns = [\n    path(\'login/\', LoginView.as_view(), name=\'knox-login\'),\n    path(\'logout/\', knox_views.LogoutView.as_view(), name="knox_logout"),\n    path(\'logoutall/\', knox_views.LogoutAllView.as_view(), name="knox_logoutall"),\n    path(\'\', include(router.urls)),\n    path(\'api-auth/\', include(\'rest_framework.urls\', namespace=\'rest_framework\'))\n]\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

我意识到,如果我覆盖显示用户模型详细信息的页面的 url,则可以修复它。但我认为有更正确的答案。

\n\n
path(\'api/users/<int:pk>/\', UserViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"}), name="customuser-detail")\n
Run Code Online (Sandbox Code Playgroud)\n

Sas*_*che 2

根据文档basename您在注册ViewSet路由器时提供的信息将用于生成 URL 模式。您提供的basename=CustomUser,其大小写。

正如错误指出的那样(另请参阅有关如何确定超链接视图和构造默认名称的文档),您的基本名称应该是小写的。

如果您想保留大写,请参阅前面的文档链接以view_name='CustomUser-detail'HyperlinkedModelSerializer.