2016-10-20 142 views
1

我知道这个问题已被问了数百次,但其中大部分都包含-accepted-已无效的答案。其中一些用于Django 1.5,其中一些甚至更老。Django 1.8+扩展用户模型

所以我正在寻找一个最新的答案。最类似于我的问题的问题是this one

我正在使用django-registration模块,我希望用户有其他字段(如整数user.points)。我很自信地执行我自己的MyUser模型并相应地更改我的程序的其余部分。不过,我怀疑这是否符合注册模块。所以我想最理想的方法是继续使用User模型,并以某种方式将它们连接起来,这样无论何时创建User对象,都会创建一个对应的MyUser对象,其中包含其他字段的默认值。

- 我怎么能用Django 1.8+做到这一点?

感谢您的帮助,

+0

它不Django的1.5和1.8,以便联答案之间的变化并不过时。 – GwynBleidD

回答

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 

UPDATE:

是还有其他的注意事项吗?就像我删除 UserProfile时发生的情况一样?

UserProfile是谁拥有的关系之一,因此上删除没有user应予删除。您可以控制当通过on_delete kwarg删除user时必须采取的行为。

也他们总是有相同的私人密钥?

没有每个类都有自己的PK,只是UserProfile持有PK到它的user

OneToOneField是在概念上与unique=True一个ForeignKey,最大的区别在于关系的反面不0/1元素返回一个列表,而是元素本身或提高DoesNotExistNone如果null=True

我不喜欢这种方法的唯一的事情是,你总是必须再做1个查询才能得到user.profile。当我从auth获取新的user时,仍然无法找到总是.select_related('profile')的良好且干净的方法,但这更多是验证系统的问题,而不是方法本身。

+0

这种方法现在看起来更合适:)任何异议? – jeff

+0

我正在用这种方法。它创建'UserProfile'作为'User'创建。我只需要像视图中的request.user.profile这样的用户,但是还有其他的注意事项吗?就像我删除UserProfile时会发生什么?相应的用户也被删除了吗?他们也一直拥有相同的私钥吗? – jeff

+0

@halilpazarlama用你的问题的一些答案更新了这个问题。我还发布了一篇文章链接,解释不同的方法及其优缺点。 – Todor

1

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

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

更多关于您可以在django-registration docs中找到。

1

首先要求扩展用户模型:你必须从一个干净的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) 
+0

非常感谢!这似乎工作正常,但我只是混淆了最后一部分(注册在'admin.py'),如果我按照你的建议,我没有看到新的领域。当我通过'admin.site.register(Account)'注册时,现在我看到了新的字段。我想知道为什么会这样。无论如何,我会接受你的答案,但我也希望能与你合作。再次感谢所有的回答者! – jeff

+0

现在注册模块给我一个错误。如果你有兴趣,这里是我的后续[问题](http://stackoverflow.com/questions/40155777/custom-user-models-in-django-no-such-table-auth-user):) – jeff

+1

我的不好,最后一部分是一些不相关的代码。我编辑了我的答案。 – idik