【问题标题】:Django 1.8+ extending the User modelDjango 1.8+ 扩展用户模型
【发布时间】:2017-03-02 09:15:36
【问题描述】:

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

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

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

-如何使用 Django 1.8+ 来做到这一点?

感谢您的帮助,

【问题讨论】:

  • 它在 Django 1.5 和 1.8 之间没有变化,所以链接的答案没有过时。

标签: python django authentication django-registration


【解决方案1】:

一篇关于该主题的文章: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

更新:

还有其他注意事项吗?就像我删除一个 用户资料?

UserProfile 是持有关系的人,所以删除 不应该删除user。您可以通过on_delete kwarg 控制user 被删除时的行为。

他们也总是拥有相同的私钥吗?

没有每个类都有自己的 PK,只有 UserProfile 将 PK 保存到其 user。

OneToOneField在概念上是一个ForeignKey和一个unique=True,最大的区别是关系的反面不返回一个包含0/1元素的列表,而是元素本身或引发DoesNotExist或None 如果null=True。

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

【讨论】:

  • 这个方法现在好像更合适了:) 有异议吗?
  • 我将采用这种方法。它在创建User 时创建UserProfile。我只需要在视图中获得像request.user.profile 这样的用户,但是还有其他警告吗?就像我删除 UserProfile 时会发生什么?对应的User也被删除了吗?他们也总是有相同的私钥吗?
  • @halilpazarlama 更新了问题,并提供了一些对您问题的答案。我还发布了一篇文章的链接,该文章解释了不同方法及其优缺点。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    AUTH_USER_MODEL = 'APPNAME.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)
    

    【讨论】:

    • 非常感谢!这似乎工作正常,但我只是对最后一部分感到困惑(在admin.py 上注册)如果我按照您建议的方式进行操作,我看不到新字段。当我简单地通过admin.site.register(Account) 注册它时,现在我看到了新字段。我想知道为什么会这样。无论如何我都会接受你的回答,但我也希望能就此进行合作。再次感谢所有回答者!
    • 现在注册模块给我一个错误。如果你有兴趣,这里是我的跟进question :)
    • 我的错,最后一部分是一些不相关的代码。我编辑了我的答案。
    猜你喜欢
    • 2016-10-12
    • 2011-02-28
    • 2013-12-06
    • 2018-01-21
    • 2018-04-24
    • 2018-01-22
    • 1970-01-01
    相关资源
    最近更新 更多