Django 1.8+ 扩展用户模型

Django 1.8+ extending the User model

我知道这个问题已被问过数百次,但其中大多数包含 - 已接受 - 不再有效的答案。其中一些适用于 Django 1.5,其中一些甚至更旧。

所以我正在寻找最新的答案。与我的问题最相似的问题是 this one.

我正在使用 django-registration 模块,我希望用户有额外的字段(如整数 user.points)。我可以实施自己的 MyUser 模型并相应地更改程序的其余部分。但是我怀疑这是否符合注册模块。所以我想理想的方法是继续使用 User 模型,并以某种方式绑定它们,以便每当创建 User 对象时,都会创建一个相应的 MyUser 对象,并使用默认值附加字段。

-我如何使用 Django 1.8+ 执行此操作?

感谢您的帮助,

一篇关于主题的文章:How to Extend Django User Model

我用的是One-To-One方法:

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name="profile")
    #more fields

    @staticmethod
    @receiver(post_save, sender=User, dispatch_uid="at_user_post_save")
    def user_post_save(sender, instance, **kwargs):
        #create new profile on user.save() (if necessary)
        profile, new = UserProfile.objects.get_or_create(user=instance)


#in view
profile = request.user.profile

更新:

Are there any other caveats? Like what happens when I remove a UserProfile?

UserProfile是持有关系的人,所以on delete no user应该删除。您可以通过 on_delete kwarg.

控制删除 user 时的行为

Also do they always have the same private keys?

没有每个 class 都有自己的 PK,只有 UserProfile 将 PK 保留到它的 user

OneToOneField 在概念上是一个 ForeignKey 和一个 unique=True,最大的区别是关系的反面不 return 一个列表与 0/ 1 个元素,但元素本身或引发 DoesNotExistNone if null=True.

我唯一不喜欢这种方法的是,您总是必须再执行 1 个查询才能获得 user.profile。当从 auth 获取新的 user 时,我仍然找不到一个好的和干净的方法来始终 .select_related('profile'),但这更多是身份验证系统的问题而不是方法本身。

django-registration支持自定义用户模型,因此创建自己的用户模型并与django-registration一起使用不会有问题。

您需要做的就是根据registration.forms.RegistrationForm创建注册表单,然后在RegistrationView中使用它。您还需要保留默认 django 用户模型中的 emailis_active 字段,并在用户模型中提供 email_user 方法。 USERNAME_FIELD 也必须指定。其他要求取决于您的身份验证方法。

您可以在 django-registration docs 中找到更多信息。

扩展用户模型的第一个要求:您必须从一个干净的 django 项目开始,您还没有调用:"python manage.py migrate" 命令。

这是因为如果您过去确实迁移过,未扩展的用户模型已经创建,django 不知道如何更改它。

现在,要选择另一个用户模型,您要做的第一件事就是 settings.py:

AUTH_USER_MODEL = 'APPNAME.Account'

建议创建一个新的应用来处理用户模型。请注意不要调用该应用程序 "account",因为它会与现有的用户模型发生冲突。

我创建了一个名为 accountb 的应用程序。在模型上:

from django.db import models
from django.contrib.auth.models import UserManager
from django.contrib.auth.models import AbstractUser

class AccountManager(UserManager):
    def create_user(self, email, password=None, **kwargs):
        if not email:
            raise ValueError('Users must have a valid email address.')
        if not kwargs.get('username'):
            raise ValueError('Users must have a valid username.')

        account = self.model(
            email=self.normalize_email(email), 
            username=kwargs.get('username'), 
            year_of_birth = kwargs.get('year_of_birth'),
            #MODEL = kwargs.get('MODEL_NAME'),
        )
        account.set_password(password)
        account.save()

        return account

    def create_superuser(self, email, password, **kwargs):
        account = self.create_user(email, password, **kwargs)
        account.is_staff = True
        account.is_superuser = True
        account.save()

        return account

class Account(AbstractUser):
    email = models.EmailField(unique=True)
    #ADD YOUR MODELS HERE

    objects = AccountManager()

    def __str__(self):
        return self.email

此外,别忘了在 admin.py 上注册它:

from django.contrib import admin
from .models import Account

admin.site.register(Account)