【问题标题】:NoReverseMatch error when creating new users through admin通过管理员创建新用户时出现 NoReverseMatch 错误
【发布时间】:2017-08-11 22:12:38
【问题描述】:

在我的 django 应用程序中,我创建了一个自定义用户模型,它扩展了 AbstractUser。我更新了AUTH_USER_MODEL 并像这样在管理员下注册了它

admin.site.register(MyUser, UserAdmin)

我运行了迁移,然后在我的管理页面下看到它列在应用程序的模型下。但是当我尝试从该页面创建一个新用户时,它给了我这个错误。

models.py 中的用户类:

class MyUser(AbstractUser):
    id = models.CharField(primary_key = True, unique = True, max_length = 50)

有什么想法吗? 编辑:更新为包含主 urls.py

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^api/', include('api.urls'))
]      

编辑 2:更新为包含堆栈跟踪

Internal Server Error: /admin/api/myuser/add/
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
  response = get_response(request)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
  response = self.process_exception_by_middleware(e, request)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
  response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 551, in wrapper
  return self.admin_site.admin_view(view)(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
  response = view_func(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
  response = view_func(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 224, in inner
  return view(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
  return bound_func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
  return func.__get__(self, type(self))(*args2, **kwargs2)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
  return bound_func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
  response = view_func(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
  return func.__get__(self, type(self))(*args2, **kwargs2)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/auth/admin.py", line 103, in add_view
  return self._add_view(request, form_url, extra_context)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/auth/admin.py", line 131, in _add_view
extra_context)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1508, in add_view
  return self.changeform_view(request, None, form_url, extra_context)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
  return bound_func(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
  response = view_func(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
  return func.__get__(self, type(self))(*args2, **kwargs2)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1408, in changeform_view
  return self._changeform_view(request, object_id, form_url, extra_context)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1453, in _changeform_view
  return self.response_add(request, new_object)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/auth/admin.py", line 211, in response_add
post_url_continue)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1052, in response_add
current_app=self.admin_site.name,
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/urls/base.py", line 91, in reverse
return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/urls/resolvers.py", line 497, in _reverse_with_prefix
  raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'api_myuser_change' with arguments '('',)' not found. 1 pattern(s) tried: ['admin/api/myuser/(.+)/change/$']

编辑 3:INSTALLED_APPS

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'api',
'django_jinja',
]

【问题讨论】:

  • 您是否尝试过从 python shell 创建用户?
  • @BillF 看起来很成功,但是当我进入管理员时,用户不在那里。让我觉得我没有正确注册自定义用户类?
  • 是您的代码中的某个或某些内容缺少参数。仔细检查您的观点。
  • @aidnani8 请显示你的 urls.py
  • 你的 id 字段对我来说真的很奇怪。您管理 id 和它的 char 类型。您是否在管理员中填写 id 字段?

标签: python django django-models django-admin


【解决方案1】:

您已将主键替换为 CharField,但您仍在使用 Django 的 UserAdmin ModelAdmin。 Django 的 UserAdmin 不要求提供 ID——它默认为空字符串。 (您可以通过检查 NoReverseMatch 异常的参数中的空字符串来验证这一点。)

您需要创建一个允许您指定 ID 的 ModelAdmin,这样它就不会以空字符串结尾。以下admin.py 将允许您指定 ID,从而摆脱您的 NoReverseMatch 异常。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import MyUser

class MyUserAdmin(UserAdmin):
    add_fieldsets = (
        (None, {
            'fields': ('id', 'username', 'password1', 'password2'),
        }),
    )

# Register your models here.
admin.site.register(MyUser, MyUserAdmin)

【讨论】:

    【解决方案2】:

    您已经在管理站点中注册了您的模型

    from django.contrib import admin 
    from django.contrib.auth.admin import UserAdmin
    from .models import User
    
    admin.site.register(User, UserAdmin)
    

    你的模型也必须带有整数 id

    class MyUser(AbstractUser):
         pass
    

    【讨论】:

      【解决方案3】:

      错误消息将网址显示为/myuser/add,而您的网址说它只定义了/myuser/change/。定义 /myuser/add 类/函数视图或更新 url 以指向添加类/函数视图。

      【讨论】:

        【解决方案4】:

        经过长时间的搜索和奋斗,我发现这个解决方案确实对我有用。它使我能够使用我的自定义从管理 UI 添加编辑 API 用户。

        您只需将此代码添加到应用程序的 admin.py 文件中,并且只需将您的自定义模型名称替换为您的模型即可正常工作。

        import typing
        from django.contrib import admin, messages
        from django.db import models
        from django.http.request import HttpRequest
        from your_app.models import your_custom_model
        from rest_framework_api_key.models import AbstractAPIKey
        
        class APIKeyModelAdmin(admin.ModelAdmin):
            model: typing.Type[AbstractAPIKey]
            list_display = (
                "prefix",
                "name",
                "created",
                "_has_expired",
                "revoked",
            )
            list_filter = ("created",)
            search_fields = ("name", "prefix", "client_id")
            def get_readonly_fields(
                self, request: HttpRequest, obj: models.Model = None
            ) -> typing.Tuple[str, ...]:
                obj = typing.cast(AbstractAPIKey, obj)
                fields: typing.Tuple[str, ...]
                fields = ("prefix",)
                if obj is not None and obj.revoked:
                    fields = fields + ("name", "revoked", "expiry_date")
                return fields
        
            def save_model(
                self,
                request: HttpRequest,
                obj: AbstractAPIKey,
                form: typing.Any = None,
                change: bool = False,
            ) -> None:
                created = not obj.pk
                if created:
                    key = self.model.objects.assign_key(obj)
                    obj.save()
                    message = (
                        "The API key for {} is: {}. ".format(obj.name, key)
                        + "Please store it somewhere safe: "
                        + "you will not be able to see it again."
                    )
                    messages.add_message(request, messages.WARNING, message)
                else:
                    obj.save()
        
        admin.site.register(your_custom_model, APIKeyModelAdmin)
        

        【讨论】: