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 个元素,但元素本身或引发 DoesNotExist
或 None
if null=True
.
我唯一不喜欢这种方法的是,您总是必须再执行 1 个查询才能获得 user.profile
。当从 auth
获取新的 user
时,我仍然找不到一个好的和干净的方法来始终 .select_related('profile')
,但这更多是身份验证系统的问题而不是方法本身。
django-registration
支持自定义用户模型,因此创建自己的用户模型并与django-registration
一起使用不会有问题。
您需要做的就是根据registration.forms.RegistrationForm
创建注册表单,然后在RegistrationView
中使用它。您还需要保留默认 django 用户模型中的 email
和 is_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)
我知道这个问题已被问过数百次,但其中大多数包含 - 已接受 - 不再有效的答案。其中一些适用于 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 个元素,但元素本身或引发 DoesNotExist
或 None
if null=True
.
我唯一不喜欢这种方法的是,您总是必须再执行 1 个查询才能获得 user.profile
。当从 auth
获取新的 user
时,我仍然找不到一个好的和干净的方法来始终 .select_related('profile')
,但这更多是身份验证系统的问题而不是方法本身。
django-registration
支持自定义用户模型,因此创建自己的用户模型并与django-registration
一起使用不会有问题。
您需要做的就是根据registration.forms.RegistrationForm
创建注册表单,然后在RegistrationView
中使用它。您还需要保留默认 django 用户模型中的 email
和 is_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)