How to Extend Django User Model 如何扩展Django用户模型
2017-08-25 14:09
876 查看
The Django’s built-in authentication system is great. For the most part we can use it out-of-the-box, saving a lot of development and testing effort. It fits most of the use cases and is very safe. But sometimes we need to do some fine adjustment so to fit
our Web application.
Commonly we want to store a few more data related to our User. If your Web application have an social appeal, you might want to store a short bio, the location of the user, and other things like that.
In this tutorial I will present the strategies you can use to simply extend the default Django User Model, so you don’t need to implement everything from scratch.
Django的内置身份验证系统非常好。 在大多数情况下,我们可以开箱即用,节省了大量的开发和测试工作。 它适合大多数用例,非常安全。 但有时我们需要做一些微调,以适应我们的Web应用程序。
通常我们想要存储与我们的用户相关的更多数据。 如果您的Web应用程序具有社会吸引力,您可能需要存储一个简短的生物,用户的位置以及其他类似的东西。
在本教程中,我将介绍您可以使用的策略来简单地扩展默认的Django用户模型,因此您不需要从头开始实现所有内容。
扩展现有用户模型的方法
Generally speaking, there are four different ways to extend the existing User model. Read below why and when to use them.一般来说,扩展现有用户模型有四种不同的方式。 阅读下面为什么和什么时候使用它们。
[b]Option 1: Using a Proxy Model使用代理模型[/b]
What is a Proxy Model?
It is a model inheritance without creating a new table in the database. It is used to change the behaviour of an existing model (e.g. default ordering, add new methods, etc.) without affecting the existing database schema.
什么是代理模型?
它是一个模型继承而不在数据库中创建一个新表。 它用于改变现有模型的行为(例如默认排序,添加新方法等),而不影响现有的数据库模式。
When should I use a Proxy Model?
You should use a Proxy Model to extend the existing User model when you don’t need to store extra information in the database, but simply add extra methods or change the model’s query Manager.
什么时候应该使用代理模型?
当您不需要在数据库中存储额外的信息时,您应该使用代理模型来扩展现有的用户模型,而只需添加额外的方法或更改模型的查询管理器。
[b]Option 2: Using One-To-One Link With a User Model (Profile)使用一对一链接与用户模型(配置文件)[/b]
What is a One-To-One Link?
It is a regular Django model that’s gonna have it’s own database table and will hold a One-To-One relationship with the existing User Model through a
什么是一对一链接?
它是一个常规的Django模型,它将拥有自己的数据库表,并通过OneToOneField与现有的用户模型保持一对一的关系。
When should I use a One-To-One Link?
You should use a One-To-One Link when you need to store extra information about the existing User Model that’s not related to the authentication process. We usually call it a User Profile.
什么时候应该使用一对一链接?
当您需要存储与认证过程无关的现有用户模型的额外信息时,应使用一对一链接。 我们通常称之为用户个人资料。
[b]Option 3: Creating a Custom User Model Extending AbstractBaseUser 创建自定义用户模型扩展AbstractBaseUser[/b]
What is a Custom User Model Extending AbstractBaseUser?
It is an entirely new User model that inherit from
It requires a special care and to update some references through the
Ideally it should be done in the begining of the project, since it will dramatically impact the database schema. Extra care while implementing it.
什么是自定义用户模型扩展AbstractBaseUser?
它是一个全新的User Model,继承自AbstractBaseUser。 它需要特别小心,并通过settings.py更新一些引用。 理想情况下,它应该在项目开始时完成,因为它会极大地影响数据库模式。 执行时要特别小心。
When should I use a Custom User Model Extending AbstractBaseUser?
You should use a Custom User Model when your application have specific requirements in relation to the authentication process. For example, in some cases it makes more sense to use an email address as your identification token instead of a username.
何时应该使用自定义用户模型扩展AbstractBaseUser?
当您的应用程序具有与身份验证过程相关的特定要求时,应使用自定义用户模型。 例如,在某些情况下,使用电子邮件地址作为识别令牌而不是用户名更有意义。
[b]Option 4: Creating a Custom User Model Extending AbstractUser 创建自定义用户模型扩展AbstractUser[/b]
What is a Custom User Model Extending AbstractUser?
It is a new User model that inherit from
It requires a special care and to update some references through the
Ideally it should be done in the begining of the project, since it will dramatically impact the database schema. Extra care while implementing it.
什么是自定义用户模型扩展AbstractUser?
它是一个继承自AbstractUser的新用户模型。 它需要特别小心,并通过settings.py更新一些引用。 理想情况下,它应该在项目开始时完成,因为它会极大地影响数据库模式。 执行时要特别小心。
When should I use a Custom User Model Extending AbstractUser?
You should use it when you are perfectly happy with how Django handles the authentication process and you wouldn’t change anything on it. Yet, you want to add some extra information directly in the User model, without having to create an extra class (like in
the Option 2).
何时应该使用自定义用户模型扩展AbstractUser?
当Django处理身份验证过程非常满意时,您应该使用它,并且不会对其进行任何更改。 但是,您可以直接在用户模型中添加一些额外的信息,而无需创建额外的类(如选项2)。
This is the less intrusive way to extend the existing User model. You won’t have any drawbacks with that strategy. But it is very limited in many ways. 这是扩展现有用户模型的侵入性较小的方式。 你不会有这个策略的任何缺点。 但是它在许多方面是非常有限的。
Here is how you do it:这是你怎么做的:
In the example above we have defined a Proxy Model named
We tell Django this is a Proxy Model by adding the following property inside the Meta class:
In this case I’ve redefined the default ordering, assigned a custom
the model, and also defined a new method
It is worth noting that
query the same database table. The only difference is in the behavior we define for the Proxy Model.
If that’s all you need, go for it. Keep it simple.
There is a good chance that this is what you want. Personally that is the method I use for the most part. We will be creating a new Django Model to store the extra information that relates to the User Model.
Bear in mind that using this strategy results in additional queries or joins to retrieve the related data. Basically all the time you access an related data, Django will fire an additional query. But this can be avoided for the most cases. I will get back to
that later on.
有一个很好的机会,这是你想要的。 就个人而言,这是我大部分使用的方法。 我们将创建一个新的Django模型来存储与用户模型相关的额外信息。
请记住,使用此策略会产生其他查询或联接来检索相关数据。 基本上所有的时间您访问相关数据,Django将触发一个额外的查询。 但是大多数情况下可以避免这种情况。 我稍后再回来。
我通常将Django模型命名为Profile:
I usually name the Django Model as
Now this is where the magic happens: we will now define signals so our
will be automatically created/updated when we create/update User instances.
Basically we are hooking the
to the User model, whenever asave event occurs. This kind of signal is called
Great stuff. Now, tell me how can I use it.
Piece of cake. Check this example in a Django Template:
How about inside a view method?
Generally speaking, you will never have to call the Profile’s save method. Everything is done through the User model.
What if I’m using Django Forms?
Did you know that you can process more than one form at once? Check out this snippet:
forms.py
views.py
profile.html
And the extra database queries you were talking about?
Oh, right. I’ve addressed this issue in another post named “Optimize Database Queries”. You can read it clicking
here.
But, long story short: Django relationships are lazy. Meaning Django will only query the database if you access one of the related properties. Sometimes it causes some undesired effects, like firing hundreds or thousands of queries. This problem can be mitigated
using the
Knowing beforehand you will need to access a related data, you can prefetch it in a single database query:
The hairy one. Well, honestly I try to avoid it at all costs. But sometimes you can’t run from it. And it is perfectly fine. There is hardly such a thing as best or worst solution. For the most part there is a more or less appropriate solution. If this is the
most appropriate solution for you case, go ahead.
I had to do it once. Honestly I don’t know if this is the cleaner way to do it, but, here goes nothing:
I needed to use email address as auth token and in the scenario the
completly useless for me. Also there was no need for the
as I wasn’t using the Django Admin.
毛茸茸的。 嗯,老实说,我尽量避免,不惜一切代价。 但是有时你不能从它跑出来。 这是非常好的。 几乎没有最好的或最差的解决方案。 在大多数情况下,有一个或多或少的适当的解决方案。 如果这是您最合适的解决方案,请继续。
我不得不这样做一次。 老实说,我不知道这是否是更干净的做法,但是什么也没有:
我需要使用电子邮件地址作为身份验证令牌,在这种情况下,用户名对我来说完全没用。 也没有必要的is_staff标志,因为我没有使用Django管理员。
这是我如何定义我自己的用户模型:
Here is how I defined my own user model:
I wanted to keep it as close as possible to the existing User model. Since we are inheriting from the
have to follow some rules:
USERNAME_FIELD: A string describing the name of the field on the User model that is used as the unique identifier. The field must be unique (i.e., have
in its definition);
REQUIRED_FIELDS: A list of the field names that will be prompted for when creating a user via the
command;
is_active: A boolean attribute that indicates whether the user is considered “active”;
get_full_name(): A longer formal identifier for the user. A common interpretation would be the full name of the user, but it can be any string that identifies the user.
get_short_name(): A short, informal identifier for the user. A common interpretation would be the first name of the user.
Okay, let’s move forward. I had also to define my own
That’s because the existing manager define the
So, here is what my
like:
Basically I’ve done a clean up of the existing
removing the
Now the final move. We have to update our settings.py. More specifically the
This way we are telling Django to use our custom model instead the default one. In the example above, I’ve created the custom model inside an app named
How should I reference this model?
Well, there are two ways. Consider a model named
This is perfectly okay. But if you are creating a reusable app, that you want to make available for the public, it is strongly advised that you use the following strategy:
This is pretty straighforward since the class
the full implementation of the default User as an abstract model.
Then we have to update our settings.py defining the
In a similar way as the previous method, this should be done ideally in the begining of a project and with an extra care. It will change the whole database schema. Also, prefer to create foreign keys to the User model importing the settings
of referring directly to the custom User model.
Alright! We’ve gone through four different ways to extend the existing User Model. I tried to give you as much details as possible. As I said before, there is no best solution. It will really depend on what you need to achieve. Keep it simple and choose
wisely. 好的! 我们已经通过四种不同的方式来扩展现有的用户模型。 我试图给你尽可能多的细节。 正如我之前所说,没有最好的解决办法。 这将取决于你需要实现什么。 保持简单,明智地选择。
Proxy Model: You are happy with everything Django User provide and don’t need to store extra information.
User Profile: You are happy with the way Django handles the auth and need to add some non-auth related attributes to the User.
Custom User Model from AbstractBaseUser: The way Django handles auth doesn’t fit your project.
Custom User Model from AbstractUser: The way Django handles auth is a perfect fit for your project but still you want to add extra attributes without having to create a separate Model.
代理模型:您对Django用户提供的所有内容感到满意,并且不需要存储额外的信息。
用户个人资料:您对Django处理验证的方式感到满意,需要向用户添加一些非验证相关的属性。
来自AbstractBaseUser的自定义用户模型:Django处理auth的方式不符合您的项目。
来自AbstractUser的自定义用户模型:Django处理auth的方式非常适合您的项目,但仍然需要添加额外的属性,而无需创建单独的模型。
our Web application.
Commonly we want to store a few more data related to our User. If your Web application have an social appeal, you might want to store a short bio, the location of the user, and other things like that.
In this tutorial I will present the strategies you can use to simply extend the default Django User Model, so you don’t need to implement everything from scratch.
Django的内置身份验证系统非常好。 在大多数情况下,我们可以开箱即用,节省了大量的开发和测试工作。 它适合大多数用例,非常安全。 但有时我们需要做一些微调,以适应我们的Web应用程序。
通常我们想要存储与我们的用户相关的更多数据。 如果您的Web应用程序具有社会吸引力,您可能需要存储一个简短的生物,用户的位置以及其他类似的东西。
在本教程中,我将介绍您可以使用的策略来简单地扩展默认的Django用户模型,因此您不需要从头开始实现所有内容。
Ways to Extend the Existing User Model
扩展现有用户模型的方法Generally speaking, there are four different ways to extend the existing User model. Read below why and when to use them.一般来说,扩展现有用户模型有四种不同的方式。 阅读下面为什么和什么时候使用它们。
[b]Option 1: Using a Proxy Model使用代理模型[/b]
What is a Proxy Model?
It is a model inheritance without creating a new table in the database. It is used to change the behaviour of an existing model (e.g. default ordering, add new methods, etc.) without affecting the existing database schema.
什么是代理模型?
它是一个模型继承而不在数据库中创建一个新表。 它用于改变现有模型的行为(例如默认排序,添加新方法等),而不影响现有的数据库模式。
When should I use a Proxy Model?
You should use a Proxy Model to extend the existing User model when you don’t need to store extra information in the database, but simply add extra methods or change the model’s query Manager.
什么时候应该使用代理模型?
当您不需要在数据库中存储额外的信息时,您应该使用代理模型来扩展现有的用户模型,而只需添加额外的方法或更改模型的查询管理器。
[b]Option 2: Using One-To-One Link With a User Model (Profile)使用一对一链接与用户模型(配置文件)[/b]
What is a One-To-One Link?
It is a regular Django model that’s gonna have it’s own database table and will hold a One-To-One relationship with the existing User Model through a
OneToOneField.
什么是一对一链接?
它是一个常规的Django模型,它将拥有自己的数据库表,并通过OneToOneField与现有的用户模型保持一对一的关系。
When should I use a One-To-One Link?
You should use a One-To-One Link when you need to store extra information about the existing User Model that’s not related to the authentication process. We usually call it a User Profile.
什么时候应该使用一对一链接?
当您需要存储与认证过程无关的现有用户模型的额外信息时,应使用一对一链接。 我们通常称之为用户个人资料。
[b]Option 3: Creating a Custom User Model Extending AbstractBaseUser 创建自定义用户模型扩展AbstractBaseUser[/b]
What is a Custom User Model Extending AbstractBaseUser?
It is an entirely new User model that inherit from
AbstractBaseUser.
It requires a special care and to update some references through the
settings.py.
Ideally it should be done in the begining of the project, since it will dramatically impact the database schema. Extra care while implementing it.
什么是自定义用户模型扩展AbstractBaseUser?
它是一个全新的User Model,继承自AbstractBaseUser。 它需要特别小心,并通过settings.py更新一些引用。 理想情况下,它应该在项目开始时完成,因为它会极大地影响数据库模式。 执行时要特别小心。
When should I use a Custom User Model Extending AbstractBaseUser?
You should use a Custom User Model when your application have specific requirements in relation to the authentication process. For example, in some cases it makes more sense to use an email address as your identification token instead of a username.
何时应该使用自定义用户模型扩展AbstractBaseUser?
当您的应用程序具有与身份验证过程相关的特定要求时,应使用自定义用户模型。 例如,在某些情况下,使用电子邮件地址作为识别令牌而不是用户名更有意义。
[b]Option 4: Creating a Custom User Model Extending AbstractUser 创建自定义用户模型扩展AbstractUser[/b]
What is a Custom User Model Extending AbstractUser?
It is a new User model that inherit from
AbstractUser.
It requires a special care and to update some references through the
settings.py.
Ideally it should be done in the begining of the project, since it will dramatically impact the database schema. Extra care while implementing it.
什么是自定义用户模型扩展AbstractUser?
它是一个继承自AbstractUser的新用户模型。 它需要特别小心,并通过settings.py更新一些引用。 理想情况下,它应该在项目开始时完成,因为它会极大地影响数据库模式。 执行时要特别小心。
When should I use a Custom User Model Extending AbstractUser?
You should use it when you are perfectly happy with how Django handles the authentication process and you wouldn’t change anything on it. Yet, you want to add some extra information directly in the User model, without having to create an extra class (like in
the Option 2).
何时应该使用自定义用户模型扩展AbstractUser?
当Django处理身份验证过程非常满意时,您应该使用它,并且不会对其进行任何更改。 但是,您可以直接在用户模型中添加一些额外的信息,而无需创建额外的类(如选项2)。
Extending User Model Using a Proxy Model 使用代理模型扩展用户模型
This is the less intrusive way to extend the existing User model. You won’t have any drawbacks with that strategy. But it is very limited in many ways. 这是扩展现有用户模型的侵入性较小的方式。 你不会有这个策略的任何缺点。 但是它在许多方面是非常有限的。Here is how you do it:这是你怎么做的:
from django.contrib.auth.models import User from .managers import PersonManager class Person(User): objects = PersonManager() class Meta: proxy = True ordering = ('first_name', ) def do_something(self): ...
In the example above we have defined a Proxy Model named
Person.
We tell Django this is a Proxy Model by adding the following property inside the Meta class:
proxy = True.
In this case I’ve redefined the default ordering, assigned a custom
Managerto
the model, and also defined a new method
do_something.
It is worth noting that
User.objects.all()and
Person.objects.all()will
query the same database table. The only difference is in the behavior we define for the Proxy Model.
If that’s all you need, go for it. Keep it simple.
Extending User Model Using a One-To-One Link使用一对一链接扩展用户模型
There is a good chance that this is what you want. Personally that is the method I use for the most part. We will be creating a new Django Model to store the extra information that relates to the User Model.Bear in mind that using this strategy results in additional queries or joins to retrieve the related data. Basically all the time you access an related data, Django will fire an additional query. But this can be avoided for the most cases. I will get back to
that later on.
有一个很好的机会,这是你想要的。 就个人而言,这是我大部分使用的方法。 我们将创建一个新的Django模型来存储与用户模型相关的额外信息。
请记住,使用此策略会产生其他查询或联接来检索相关数据。 基本上所有的时间您访问相关数据,Django将触发一个额外的查询。 但是大多数情况下可以避免这种情况。 我稍后再回来。
我通常将Django模型命名为Profile:
I usually name the Django Model as
Profile:
from django.db import models from django.contrib.auth.models import User class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(max_length=500, blank=True) location = models.CharField(max_length=30, blank=True) birth_date = models.DateField(null=True, blank=True)
Now this is where the magic happens: we will now define signals so our
Profilemodel
will be automatically created/updated when we create/update User instances.
from django.db import models from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(max_length=500, blank=True) location = models.CharField(max_length=30, blank=True) birth_date = models.DateField(null=True, blank=True) @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
Basically we are hooking the
create_user_profileand
save_user_profilemethods
to the User model, whenever asave event occurs. This kind of signal is called
post_save.
Great stuff. Now, tell me how can I use it.
Piece of cake. Check this example in a Django Template:
<h2>{{ user.get_full_name }}</h2> <ul> <li>Username: {{ user.username }}</li> <li>Location: {{ user.profile.location }}</li> <li>Birth Date: {{ user.profile.birth_date }}</li> </ul>
How about inside a view method?
def update_profile(request, user_id): user = User.objects.get(pk=user_id) user.profile.bio = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit...' user.save()
Generally speaking, you will never have to call the Profile’s save method. Everything is done through the User model.
What if I’m using Django Forms?
Did you know that you can process more than one form at once? Check out this snippet:
forms.py
class UserForm(forms.ModelForm): class Meta: model = User fields = ('first_name', 'last_name', 'email') class ProfileForm(forms.ModelForm): class Meta: model = Profile fields = ('url', 'location', 'company')
views.py
@login_required @transaction.atomic def update_profile(request): if request.method == 'POST': user_form = UserForm(request.POST, instance=request.user) profile_form = ProfileForm(request.POST, instance=request.user.profile) if user_form.is_valid() and profile_form.is_valid(): user_form.save() profile_form.save() messages.success(request, _('Your profile was successfully updated!')) return redirect('settings:profile') else: messages.error(request, _('Please correct the error below.')) else: user_form = UserForm(instance=request.user) profile_form = ProfileForm(instance=request.user.profile) return render(request, 'profiles/profile.html', { 'user_form': user_form, 'profile_form': profile_form })
profile.html
<form method="post"> {% csrf_token %} {{ user_form.as_p }} {{ profile_form.as_p }} <button type="submit">Save changes</button> </form>
And the extra database queries you were talking about?
Oh, right. I’ve addressed this issue in another post named “Optimize Database Queries”. You can read it clicking
here.
But, long story short: Django relationships are lazy. Meaning Django will only query the database if you access one of the related properties. Sometimes it causes some undesired effects, like firing hundreds or thousands of queries. This problem can be mitigated
using the
select_relatedmethod.
Knowing beforehand you will need to access a related data, you can prefetch it in a single database query:
users = User.objects.all().select_related('profile')
Extending User Model Using a Custom Model Extending AbstractBaseUser
使用自定义模型扩展用户模型扩展AbstractBaseUser
The hairy one. Well, honestly I try to avoid it at all costs. But sometimes you can’t run from it. And it is perfectly fine. There is hardly such a thing as best or worst solution. For the most part there is a more or less appropriate solution. If this is themost appropriate solution for you case, go ahead.
I had to do it once. Honestly I don’t know if this is the cleaner way to do it, but, here goes nothing:
I needed to use email address as auth token and in the scenario the
usernamewas
completly useless for me. Also there was no need for the
is_staffflag,
as I wasn’t using the Django Admin.
毛茸茸的。 嗯,老实说,我尽量避免,不惜一切代价。 但是有时你不能从它跑出来。 这是非常好的。 几乎没有最好的或最差的解决方案。 在大多数情况下,有一个或多或少的适当的解决方案。 如果这是您最合适的解决方案,请继续。
我不得不这样做一次。 老实说,我不知道这是否是更干净的做法,但是什么也没有:
我需要使用电子邮件地址作为身份验证令牌,在这种情况下,用户名对我来说完全没用。 也没有必要的is_staff标志,因为我没有使用Django管理员。
这是我如何定义我自己的用户模型:
Here is how I defined my own user model:
from __future__ import unicode_literals from django.db import models from django.core.mail import send_mail from django.contrib.auth.models import PermissionsMixin from django.contrib.auth.base_user import AbstractBaseUser from django.utils.translation import ugettext_lazy as _ from .managers import UserManager class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(_('email address'), unique=True) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=30, blank=True) date_joined = models.DateTimeField(_('date joined'), auto_now_add=True) is_active = models.BooleanField(_('active'), default=True) avatar = models.ImageField(upload_to='avatars/', null=True, blank=True) objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] class Meta: verbose_name = _('user') verbose_name_plural = _('users') 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)
I wanted to keep it as close as possible to the existing User model. Since we are inheriting from the
AbstractBaseUserwe
have to follow some rules:
USERNAME_FIELD: A string describing the name of the field on the User model that is used as the unique identifier. The field must be unique (i.e., have
unique=Trueset
in its definition);
REQUIRED_FIELDS: A list of the field names that will be prompted for when creating a user via the
createsuperusermanagement
command;
is_active: A boolean attribute that indicates whether the user is considered “active”;
get_full_name(): A longer formal identifier for the user. A common interpretation would be the full name of the user, but it can be any string that identifies the user.
get_short_name(): A short, informal identifier for the user. A common interpretation would be the first name of the user.
Okay, let’s move forward. I had also to define my own
UserManager.
That’s because the existing manager define the
create_userand
create_superusermethods.
So, here is what my
UserManagerlooks
like:
from django.contrib.auth.base_user import BaseUserManager class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): """ Creates and saves a User with the given 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, password=None, **extra_fields): 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_superuser', 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)
Basically I’ve done a clean up of the existing
UserManager,
removing the
usernameand the
is_staffproperty.
Now the final move. We have to update our settings.py. More specifically the
AUTH_USER_MODELproperty.
AUTH_USER_MODEL = 'core.User'
This way we are telling Django to use our custom model instead the default one. In the example above, I’ve created the custom model inside an app named
core.
How should I reference this model?
Well, there are two ways. Consider a model named
Course:
from django.db import models from testapp.core.models import User class Course(models.Model): slug = models.SlugField(max_length=100) name = models.CharField(max_length=100) tutor = models.ForeignKey(User, on_delete=models.CASCADE)
This is perfectly okay. But if you are creating a reusable app, that you want to make available for the public, it is strongly advised that you use the following strategy:
from django.db import models from django.conf import settings class Course(models.Model): slug = models.SlugField(max_length=100) name = models.CharField(max_length=100) tutor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Extending User Model Using a Custom Model Extending AbstractUser
使用自定义模型扩展用户模型扩展AbstractUser
This is pretty straighforward since the class django.contrib.auth.models.AbstractUserprovides
the full implementation of the default User as an abstract model.
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): bio = models.TextField(max_length=500, blank=True) location = models.CharField(max_length=30, blank=True) birth_date = models.DateField(null=True, blank=True)
Then we have to update our settings.py defining the
AUTH_USER_MODELproperty.
AUTH_USER_MODEL = 'core.User'
In a similar way as the previous method, this should be done ideally in the begining of a project and with an extra care. It will change the whole database schema. Also, prefer to create foreign keys to the User model importing the settings
from django.conf import settingsand referring to the
settings.AUTH_USER_MODELinstead
of referring directly to the custom User model.
Conclusions
Alright! We’ve gone through four different ways to extend the existing User Model. I tried to give you as much details as possible. As I said before, there is no best solution. It will really depend on what you need to achieve. Keep it simple and choosewisely. 好的! 我们已经通过四种不同的方式来扩展现有的用户模型。 我试图给你尽可能多的细节。 正如我之前所说,没有最好的解决办法。 这将取决于你需要实现什么。 保持简单,明智地选择。
Proxy Model: You are happy with everything Django User provide and don’t need to store extra information.
User Profile: You are happy with the way Django handles the auth and need to add some non-auth related attributes to the User.
Custom User Model from AbstractBaseUser: The way Django handles auth doesn’t fit your project.
Custom User Model from AbstractUser: The way Django handles auth is a perfect fit for your project but still you want to add extra attributes without having to create a separate Model.
代理模型:您对Django用户提供的所有内容感到满意,并且不需要存储额外的信息。
用户个人资料:您对Django处理验证的方式感到满意,需要向用户添加一些非验证相关的属性。
来自AbstractBaseUser的自定义用户模型:Django处理auth的方式不符合您的项目。
来自AbstractUser的自定义用户模型:Django处理auth的方式非常适合您的项目,但仍然需要添加额外的属性,而无需创建单独的模型。
相关文章推荐
- How to Extend Django User Model
- 如何量化用户体验UE(How To Quantify The User Experience)
- XAF 如何扩展应用程序模型(How to: Extend the Application Model )<一> ListView显示页脚信息
- How to use the windows active directory to authenticate user via logon form 如何自定义权限系统,使用 active directory验证用户登录
- How to Save an ARIMA Time Series Forecasting Model in Python (如何在Python中保存ARIMA时间序列预测模型)
- How to Build an Economic Model in Your Spare Time (如何利用业余时间建立经济模型)
- 如何量化用户体验UE(How To Quantify The User Experience)[网摘]
- How To Quantify The User Experience(如何量化用户体验UE)
- How to use user script (custom script)如何使用用户脚本之Chrome
- How to replace a Django model field with a property
- Django笔记 如何扩展User表的字段
- How to Retrain Inception's Final Layer for New Categories - 如何为新的类别重复训练初始模型的最后一层
- SNMP--How to install SNMP extension agent DLL(如何安装SNMP扩展代理DLL)
- (翻译)如何避免对用户体验设计过程产生倦怠(How to Avoid UX Burnout)
- [备忘]how to use user-provided mentalray shader in Maya?(如何在maya里用自定义mentalray shader)
- How to set the current user on the model instance in the admin:
- django 自定义用户user模型的三种方法
- 06.Django中用户的两种扩展方式(Profile和AbstractUser)
- 【译】GNU Radio How to write a block 【如何开发用户模块及编写功能块】
- [SharePoint]javascript client object model 获取lookup 类型的field的值,包括user类型(单人或者多人)的值。how to get the multiple user type/lookup type field value by Javascript client object model