【问题标题】:Django custom user model: initial migration depends on migration for default auth appDjango 自定义用户模型:初始迁移取决于默认身份验证应用程序的迁移
【发布时间】:2017-02-05 17:51:01
【问题描述】:

我正在开发一个新的 Django 应用程序,并在创建任何用户或执行任何实际工作之前转移到一个名为 accounts 的应用程序提供的自定义用户模型。这似乎很顺利——我已经创建了几个用户并自定义了管理员,以便我可以从那里编辑和创建用户。

我将我的 repo 克隆到另一台计算机并在尝试启动开发服务器时遇到错误:

这是有道理的,因为我在我的项目目录中找不到任何 auth 迁移。但是,当我在我的主开发机器上创建一个新数据库并运行 ./manage.py migrate 时,输出包括 auth 应用程序的 8 个迁移:

在我的辅助机器上,我可以注释掉 accounts 初始迁移中的依赖关系,一切似乎都运行良好 - 开发服务器启动,我可以看到从我的主开发机器添加的用户(我正在使用现在是一个 sqlite3 DB),并且我需要使用 Django 管理员。

我认为依赖可能是某种遗留物,所以我想我可以删除引用。但是,如果我注释掉对我的开发机器的依赖并尝试迁移新数据库,我会收到错误消息。

我被难住了——如果我没有实际的迁移文件,这些 auth 迁移在哪里?它们是django.contrib.auth 的内置插件吗?

编辑:看起来auth 迁移是内置的,那么为什么在我的第二台机器上尝试启动开发服务器时我的项目无法访问它们?我已经尝试专门为 auth 应用程序进行迁移以确保它们存在,但它报告没有任何更改。

作为参考,这是我的accounts 模特和经理:

# accounts/models.py
"""
This model defines the custom user object
The main object of this user model is to use email as the
main unique field and remove username as a required field
"""

from django.contrib import auth
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.contrib.auth.signals import user_logged_in
from django.contrib.contenttypes.models import ContentType
from django.core import validators
from django.core.exceptions import PermissionDenied
from django.core.mail import send_mail
from django.db import models
from django.db.models.manager import EmptyManager
from django.utils import six, timezone
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, username=None, **extra_fields):
        """
        Creates and saves a User with the given username, email and password.
        """
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, username=None, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
    """
    A base class implementing a fully featured User model with
    admin-compliant permissions.
    Email and password are required. Other fields are optional.
    """
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    username = models.CharField(
        _('username'),
        max_length=150,
        blank=True,
        null=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(
                r'^[\w.@+-]+$',
                _('Enter a valid username. This value may contain only '
                  'letters, numbers ' 'and @/./+/-/_ characters.')
            ),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    email = models.EmailField(
        _('Email Address'), unique=True,
        error_messages={
            'unique': _("A user with that email already exists."),
        }
    )
    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    #app-specific user fields
    has_picked = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        #abstract = True

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        "Returns the short name for the user."
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email], **kwargs)

    @property
    def display_name(self):
        """
        Returns first name and last initial, first name, or email prefix
        Depending on whats available
        """
        if self.first_name:
            if self.last_name:
                return self.first_name + ' ' + self.last_name[0] + '.'
            else:
                return self.first_name
        else:
            return self.email.split('@')[0]

还有我的 INSTALLED_APPS:

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

【问题讨论】:

  • 是的,它们是内置的。您在 INSTALLED_APPS 中有 auth 应用吗?
  • 是的,我愿意。我应该在问题中包含我的 INSTALLED_APPS。现在添加那些
  • 那你还有什么问题?
  • 我仍然不确定我的项目出了什么问题。我无法在我的第二台机器上启动开发服务器,除非我的accounts 应用程序的第一次迁移对auth.0008_alter_user_username_max_length 的依赖被注释掉了。 auth 在已安装的应用程序中,这里有什么问题?

标签: django django-models


【解决方案1】:

身份验证应用程序中的迁移 0008 已在 Django 1.10 中添加。您可能正在另一台机器上运行旧版本的 Django。

【讨论】:

  • 拍,谢谢。完全正确——我知道我的版本不同,但我从未想过它可能是罪魁祸首。非常感谢!
猜你喜欢
  • 2016-10-07
  • 2017-02-19
  • 2012-05-23
  • 2011-04-11
  • 2017-03-18
  • 1970-01-01
  • 2017-08-05
  • 2021-09-27
相关资源
最近更新 更多