【问题标题】:lazy reference: doesn't provide model user?懒惰参考:不提供模型用户?
【发布时间】:2018-04-14 00:38:38
【问题描述】:

目前我正在使用 Django 1.11 和 Python 3.6。我正在尝试使用通过 LDAP 进行身份验证的新应用程序创建自定义用户模型,但收到以下错误消息。

    raise ValueError("\n".join(error.msg for error in errors))
ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'accounts.user', but app 'accounts' doesn't provide model 'user'.

Settings.py 已安装的应用程序、身份验证后端和 Auth_User 模型:

INSTALLED_APPS = [
    'django_python3_ldap',
    'django_extensions',
    'django_filters',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts',
]


AUTHENTICATION_BACKENDS = (
    'django_python3_ldap.auth.LDAPBackend',
    'django.contrib.auth.backends.ModelBackend',
)

AUTH_USER_MODEL = "accounts.User"

Admin.py:

from django.contrib import admin
from django.conf import settings
from .models import User

# Register your models here.
admin.site.register(User)

下面是我的models.py:

from __future__ import unicode_literals
from django.utils import timezone
from django.contrib.auth.models import (AbstractBaseUser,PermissionsMixin)
from django.db import models
from django.forms import ModelForm


class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=25, unique=True)
    first_name = models.CharField(max_length=40)
    last_name = models.CharField(max_length=140)
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    facility = models.CharField(max_length=140)
    jobdescription = models.CharField(max_length=140)
    positiondescription = models.CharField(max_length=140)

    USERNAME_FIELD = "username"

【问题讨论】:

  • 您确定 AUTH_USER_MODEL 设置为 accounts.User 而不是 accounts.user
  • 我确定,上面是复制粘贴的。

标签: django django-models


【解决方案1】:

这个:

这是由您的设置引起的。AUTH_USER_MODEL 已更改为在计算迁移时不存在的模型。

...@AKXtheir answer below 中提到的给了我一个可行的想法。

我做了以下事情:

  1. 尽一切努力将您的自定义User 模型放置到位。在settings.py 中设置AUTH_USER_MODEL,并使用您的自定义用户模型更新django.contrib.auth.models.User 的任何使用。
  2. 运行python manage.py makemigrations
  3. 撤消步骤 1
  4. 运行python manage.py migrate
  5. 重做步骤 1

【讨论】:

  • 我知道这是一个旧答案,但这对我的团队非常有帮助,我想说声谢谢。这应该是公认的答案。
  • 嗨,我没有应用这个。这是我所做的,创建了新用户(身份验证)应用程序,设置 AUTH_USER_MODEL (1)。跑makemigrations (2)。删除了 AUTH_USER_MODEL 设置,评论了 CustomUser 模型 (3)。尝试应用迁移时遇到错误 No migrations to apply 并指示我再次运行 makemigrations 并重新应用。我哪里错了。此外,此解决方案是否保留现有数据?如果是这样,我应该在哪里/何时将想法设置为现有的 auth_user 表? @user65909 你能帮忙吗?
  • @RedgrenGrumbholdt 嗨,我刚才回答了这个问题,不记得细节了,我想我不能帮忙,对不起!
【解决方案2】:

对我来说帮助分裂了两次迁移

  1. 新建表(新旧表之间没有连接,也没有AUTH_USER_MODEL = 'accounts.User'
  2. AUTH_USER_MODEL 添加到settings.py 以及与新表的其他连接

但它适用于开发/生产数据库,如果您想在测试中应用迁移或从头开始创建数据库,您应该“压缩迁移”,对我来说这是下一步:

  1. 转储一个数据库(在我的例子中是sqldump
  2. 清理数据库(尤其是表django_migrations
  3. 删除项目中的所有迁移
  4. 运行manage.py makemigrations
  5. 添加迁移以添加旧迁移中的所有数据插入
  6. 运行manage.py migrate
  7. 删除转储中的表 django_migrations(可能还有其他一些 django_* 表)
  8. 从转储中恢复数据库

【讨论】:

  • 还要注意下面@daka 的解决方案,它通过一次迁移来完成。
【解决方案3】:

这是由于您的 settings.AUTH_USER_MODEL 已更改为在计算迁移时不存在的模型。

如果您要从 auth.User 迁移到 custom.User,在不丢失数据的情况下解决此问题的一种稍微老套的方法是添加一个“虚拟”(单独的数据库和状态)最小模型(也就是说,只有 ID 字段,以允许外键)根据新的用户模型在最初的迁移中,所以未来的迁移有这个参考:

operations=[
    migrations.SeparateDatabaseAndState(
        state_operations=[
            migrations.CreateModel(
                name="User",
                fields=[
                    (
                        "id",
                        models.AutoField(
                            auto_created=True,
                            primary_key=True,
                            serialize=False,
                            verbose_name="ID",
                        ),
                    )
                ],
                options={"db_table": "auth_user"},
                managers=[("objects", UserManager())],
            )
        ]
    ),
    # ... other migrations

【讨论】:

  • 伙计,你是天才!没有“删除所有迁移并享受”的唯一解决方案。
  • 我意识到你实际上不能用这个 hack 运行从零到当前状态的迁移,因为指向用户模型的外键会被破坏。这可以通过将创建新用户模型的完整 CreateModel 表达式复制到初始迁移中来解决。
  • 这仍然是 Django 3.0.7 中的一个东西,尝试了一个从头开始的应用程序,但我的 AUTH_USER_MODEL 从未进入迁移。
  • 请注意,这仅在输入0001_initial.py 时有效。顺便说一句,很好的修复
  • 很好的答案。除了 Jurrian 的说明,这应该放在 0001_initial.py 中,您应该注意您还需要将“from django.contrib.auth.models import UserManager”添加到 0001_initial.py,如果您的用户修改 name="User"模型被命名为不同的东西(我的是 AuthUser)
【解决方案4】:

警告:它将删除您的整个数据库。如果您有一些重要数据,请通过 dumpdata 备份,然后通过 loaddata 恢复。 for more info check here (I am not sure about this).

在项目中间更改 AUTH_USER_MODEL 非常困难。 See the note in the docs。 在您完成第一次 Django 表迁移后感染,您将面临问题。

想法是:您需要将 自定义用户模型 及其条目包含在 setting.py (AUTH_USER_MODEL = [custom user model] ) 中- Django 项目的永远迁移(django 创建自己的表,如 auth_group、dajango_migrations 等...)。

警告:如果你已经启动了服务器,那么 Django 自己创建数据库然后这将不起作用,所以请不要启动服务器。

  • 删除 dbsqlite3 数据库文件,删除除 init 文件之外的所有迁移文件及其二进制文件(在 app/migration/pycache 中)并注释掉所有模型及其依赖项(例如,您使用过任何形式的模型,然后评论它)。
  • 现在只取消注释自定义用户模型
  • 在 setting.py 中添加 AUTH_USER_MODEL (AUTH_USER_MODEL = [自定义用户模型])
  • 然后运行 ​​makemigrations 并迁移。 (这将创建您的所有 Django 表和您的自定义用户模型。)

完成了。

现在您可以启动服务器了。

之后取消注释所有其他模型并迁移它们。

【讨论】:

  • 对于某些情况,这可能是唯一的解决方案,如果您处于开发初期,那么绝对值得清除您的数据库并在第一时间获得正确的架构。如果您正在与其他人一起工作,您可能会为他们做一个注释,不要简单地拉下您的代码并应用迁移,而是删除他们的本地 sqlite 数据库。
【解决方案5】:

或者,您也可以尝试:

  1. 在包含自定义用户模型的应用上执行python manage.py migrate <app_name>
  2. 执行python manage.py migrate 以应用应用程序的其余迁移。

之所以可行,是因为您首先应用了新用户模型的更改,然后再应用了 Django 中构建的 auth 模型的其余部分。

不知道我解释的对不对

【讨论】:

  • 这真的很有帮助..谢谢!
【解决方案6】:

警告:它将破坏您当前的用户/组/身份验证表和与用户模型相关的条目

其实在django 1.9+这就够了:

  • 使用以下语句删除所有auth_*django_admin_log 表:

DROP TABLE django_admin_log, auth_group, auth_group_permissions, auth_permission, auth_user, auth_user_groups, auth_user_user_permissions CASCADE;

  • 删除与django_adminauth 应用相关的所有迁移:

DELETE FROM django_migrations WHERE app='admin' or app='auth';

  • 然后简单地运行:

./manage.py migrate

【讨论】:

    【解决方案7】:

    显然代码没有任何问题,我只需要删除所有用户表并运行 makemigration 和迁移。

    【讨论】:

    • 这样做几乎不是一个好主意。如果您在本地数据库上执行此操作,很可能最终会在您的 DEV/PROD 服务器上搞砸。
    • “我只需要删除我所有的用户表”是一个无意义的陈述。 “Just”意味着做一些非侵入性和微不足道的事情。而您建议采取最具破坏性的行动。
    • 这个真的不行
    【解决方案8】:

    按照以下说明进行操作

    1. 创建数据库备份: pg_dump -U user_name -d database_name --data-only > file_name.sql
    2. 使用运行命令转到 .sql 文件路径并重命名: sed -i 's/auth_user/custom_user/g' file_name.sql
    3. 进入sql终端运行命令: =# select '如果存在则删除表 "' || 表名 || '" 级联;'从 pg_tables where schemaname = 'public'; =#\gexec
    4. 找到 . -path "/migrations/.py" -not -name "init.py" -delete
    5. 找到 . -path "/migrations/.pyc" -delete
    6. python manage.py makemigrations
    7. python manage.py 迁移
    8. 使用以下命令将 .sql 文件加载到数据库: psql -U 用户名 -d 数据库名 -f 文件名.sql

    【讨论】:

      【解决方案9】:

      user=models.OneToOneField(User,on_delete=models.PROTECT)

      【讨论】:

        【解决方案10】:

        删除迁移目录下的所有迁移

        现在你可以使用 makemigrations 和 migrate

        【讨论】:

        • Django 拥有迁移记录,因此如果您有生产环境并且关心更改,那么简单地删除目录并不是您想要做的事情。这也可能根本没有帮助。
        猜你喜欢
        • 2017-03-05
        • 2019-05-13
        • 2017-07-24
        • 1970-01-01
        • 2019-05-22
        • 1970-01-01
        • 1970-01-01
        • 2015-09-06
        • 2022-12-10
        相关资源
        最近更新 更多