加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

自定义 Django的User Model,扩展 AbstractUser类注意事项

发布时间:2020-12-15 17:21:06 所属栏目:大数据 来源:网络整理
导读:div class="post" p class="postTitle"本篇主要讨论一下User Model的使用技巧. 注意,由于Django 1.5之后user model带来了很大的变化,本篇内容只针对django 1.5之后的版本. div class="postBody" div id="cnblogs_post_body" class="blogpost-body" 1. 确定 U

<div class="post">
<p class="postTitle">本篇主要讨论一下User Model的使用技巧. 注意,由于Django 1.5之后user model带来了很大的变化,本篇内容只针对django 1.5之后的版本.


<div class="postBody">
<div id="cnblogs_post_body" class="blogpost-body">

1. 确定 User Model

我们推荐一下方式来确定某一django项目使用的user model:

>>> >>>< ># 使用自定义User model时 </span>>>> <span style="color: #0000ff;"&gt;from</span><span style="color: #000000;"&gt; django.contrib.auth import get_user_model </span>>>><span style="color: #000000;"&gt; get_user_model() </span><<span style="color: #0000ff;"&gt;class</span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;xxx.models.UserProfile</span><span style="color: #800000;"&gt;'</span>></pre>

2. 使用settings.AUTH_USER_MODEL

自从django 1.5之后,用户可以自定义User model了,如果需要外键使用user model,官方推荐的方法如下:

在settings中设置AUTH_USER_MODEL:

.=

在models.py中使用

</span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; Article(models.Model): author </span>=<span style="color: #000000;"&gt; models.ForeignKey(settings.AUTH_USER_MODEL) title </span>= models.CharField(max_length=<span style="color: #800080;"&gt;255</span>)</pre>

还有需要注意的是,不要在外键中使用get_user_model().

3. 自定义 User Model

方法1: 扩展 AbstractUser类

如果你对django自带的User model刚到满意,又希望额外的field的话,你可以扩展AbstractUser类:

# myapp/</span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; NewUser(AbstractUser): new_field </span>= models.CharField(max_length=<span style="color: #800080;"&gt;100</span>)</pre>

不要忘了在settings.py中设置:

AUTH_USER_MODEL =

方法2: 扩展 AbstractBaseUser类

AbstractBaseUser中只含有3个field: password,last_login和is_active. 如果你对django user model默认的first_name,last_name不满意,或者只想保留默认的密码储存方式,则可以选择这一方式.

方法3: 使用OneToOneField

如果你想建立一个第三方模块发布在PyPi上,这一模块需要根据用户储存每个用户的额外信息. 或者我们的django项目中希望不同的用户拥有不同的field,有些用户则需要不同field的组合,且我们使用了方法1或方法2:

# profiles/</span><span style="color: #0000ff;"&gt;from</span><span style="color: #000000;"&gt; flavors.models import Flavor </span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; EasterProfile(models.Model): user </span>=<span style="color: #000000;"&gt; models.OneToOneField(settings.AUTH_USER_MODEL) favorite_ice_cream </span>= models.ForeignKey(Flavor,<span style="color: #0000ff;"&gt;null</span>=True,blank=<span style="color: #000000;"&gt;True) </span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; ScooperProfile(models.Model): user </span>=<span style="color: #000000;"&gt; models.OneToOneField(settings.AUTH_USER_MODEL) scoops_scooped </span>= models.IntergerField(<span style="color: #0000ff;"&gt;default</span>=<span style="color: #800080;"&gt;0</span><span style="color: #000000;"&gt;) </span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; InventorProfile(models.Model): user </span>=<span style="color: #000000;"&gt; models.OneToOneField(settings.AUTH_USER_MODEL) flavors_invented </span>= models.ManyToManyField(Flavor,blank=True)</pre>

使用以上方法,我们可以使用user.easterprofile.favorite_ice_cream获取相应的profile.

使用这一方法的坏处可能就是增加了代码的复杂性.

原文链接:

另外一篇参考文章

django——重写用户模型

Django内建的User模型可能不适合某些类型的项目。例如,在某些网站上使用邮件地址而不是用户名作为身份的标识可能更合理。

1.修改配置文件,覆盖默认的User模型

Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python plain">AUTH_USER_MODEL <code class="python keyword">= <code class="python string">'myapp.MyUser'

</td>

</tr>

</table>

上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。

注意:
1.在创建任何迁移或者第一次运行 manager.py migrate 前设置 AUTH_USER_MODEL
设置AUTH_USER_MODEL对你的数据库结构有很大的影响。它改变了一些会使用到的表格,并且会影响到一些外键和多对多关系的构造。在你有表格被创建后更改此设置是不被 makemigrations 支持的,并且会导致你需要手动修改数据库结构,从旧用户表中导出数据,可能重新应用一些迁移。

警告 :
1.确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建
由于Django的可交换模型的动态依赖特性的局限,你必须确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建(通常命名为 0001_initial),否则你会碰到错误。

The easiest way to construct a compliant custom User model is to inherit fromAbstractBaseUser. AbstractBaseUser provides the core implementation of a Usermodel,including hashed passwords and tokenized password resets. You must then provide some key implementation details:

2.引用User模型

AUTH_USER_MODEL 设置为自定义用户模型时,如果你直接引用User(例如:通过一个外键引用它),你的代码将不能工作。你应该使用django.contrib.auth.get_user_model()来引用用户模型————指定的自定义用户模型或者User

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">from <code class="python plain">django.contrib.auth <code class="python keyword">import <code class="python plain">get_user_model


<div class="line number2 index1 alt1">

<div class="line number3 index2 alt2"><code class="python plain">User <code class="python keyword">= <code class="python plain">get_user_model()

</td>

</tr>

</table>

当你定义一个外键或者到用户模型的多对多关系是,你应该使用AUTH_USER_MODEL设置来指定自定义的模型。

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">from <code class="python plain">django.conf <code class="python keyword">import <code class="python plain">settings


<div class="line number2 index1 alt1"><code class="python keyword">from <code class="python plain">django.db <code class="python keyword">import <code class="python plain">models

<div class="line number3 index2 alt2">

<div class="line number4 index3 alt1"><code class="python keyword">class <code class="python plain">Article(models.Model):

<div class="line number5 index4 alt2"><code class="python spaces"><code class="python plain">author <code class="python keyword">= <code class="python plain">models.ForeignKey(settings.AUTH_USER_MODEL)

</td>

</tr>

</table>

一般来说,在导入时候执行的代码中,你应该使用 AUTH_USER_MODEL 设置引用用户模型。get_user_model() 只在Django已经导入所有的模型后才工作。

3.指定自定义的用户模型

3.1 Django 期望你自定义的 User model 满足一些最低要求:

  1. 模型必须有一个唯一的字段可被用于识别目的。可以是一个用户名,电子邮件地址,或任何其它独特属性。
  2. 定制一个User Model最简单的方式是构造一个兼容的用户模型继承于AbstractBaseUser
    AbstractBaseUser提供了User类最核心的实现,包括哈希的passwords和 标识的密码重置。

3.2 下面为一些AbstractBaseUser的子类必须定义的关键的字段和方法:

USERNAME_FIELD
必须设置。 设置认证标识,设置成标识的字段 unique=True

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">class <code class="python plain">MyUser(AbstractBaseUser):


<div class="line number2 index1 alt1"><code class="python spaces"><code class="python plain">identifier <code class="python keyword">= <code class="python plain">models.CharField(max_length<code class="python keyword">=<code class="python value">40<code class="python plain">,unique<code class="python keyword">=<code class="python color1">True<code class="python plain">)

<div class="line number3 index2 alt2"><code class="python spaces"><code class="python plain">...

<div class="line number4 index3 alt1"><code class="python spaces"><code class="python plain">USERNAME_FIELD <code class="python keyword">= <code class="python string">'identifier'

</td>

</tr>

</table>

REQUIRED_FIELDS
必须设置。当通过createsuperuser管理命令创建一个用户时,用于提示的一个字段名称列表。

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">class <code class="python plain">MyUser(AbstractBaseUser):


<div class="line number2 index1 alt1"><code class="python spaces"><code class="python plain">...

<div class="line number3 index2 alt2"><code class="python spaces"><code class="python plain">date_of_birth <code class="python keyword">= <code class="python plain">models.DateField()

<div class="line number4 index3 alt1"><code class="python spaces"><code class="python plain">height <code class="python keyword">= <code class="python plain">models.FloatField()

<div class="line number5 index4 alt2"><code class="python spaces"><code class="python plain">...

<div class="line number6 index5 alt1"><code class="python spaces"><code class="python plain">REQUIRED_FIELDS <code class="python keyword">= <code class="python plain">[<code class="python string">'date_of_birth'<code class="python plain">,<code class="python string">'height'<code class="python plain">]

</td>

</tr>

</table>

列表中不应该包含USERNAME_FIELD字段和password字段。

is_active
必须定义。 一个布尔属性,标识用户是否是 "active" 的。AbstractBaseUser默认为 Ture

get_full_name()
必须定义。 long格式的用户标识。

get_short_name()
必须定义。 short格式的用户标识。

3.3 下面为一些AbstractBaseUser的子类可以使用的方法:

get_username()
返回 USERNAME_FIELD 的值。

is_anonymous()
一直返回 False。用来区分 AnonymousUser。

is_authenticated()
一直返回 Ture。用来告诉用户已被认证。

set_password(raw_password)
设置密码。按照给定的原始字符串设置用户的密码,taking care of the password hashing。 不保存 AbstractBaseUser 对象。如果没有给定密码,密码就会被设置成不使用,同用set_unusable_password()。

check_password(raw_password)
检查密码是否正确。 给定的密码正确返回 True。

set_unusable_password()
设置user无密码。 不同于密码为空,如果使用 check_password(),则不会返回True。不保存AbstractBaseUser 对象。

has_usable_password()
如果设置了set_unusable_password(),返回False。

get_session_auth_hash()
返回密码字段的HMAC。 Used for Session invalidation on password change.

3.4 为你的User模型自定义一个管理器

如果你的User模型定义了这些字段:username,email,is_staff,is_active,is_superuser,last_login,and date_joined跟默认的User没什么区别,那么你还不如仅仅替换Django的UserManager就行了; 总之,如果你的User定义了不同的字段,你就要去自定义一个管理器,它继承自BaseUserManager并提供两个额外的方法:

create_user(username_field,password=None,other_fields)**
接受username field和required字段来创建用户。例如,如果使用email作为username field, date_of_birth作为required field:

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">def <code class="python plain">create_user(<code class="python color1">self<code class="python plain">,date_of_birth,password<code class="python keyword">=<code class="python color1">None<code class="python plain">):


<div class="line number2 index1 alt1"><code class="python spaces"><code class="python comments"># create user here

<div class="line number3 index2 alt2"><code class="python spaces"><code class="python plain">...

</td>

</tr>

</table>

create_superuser(username_field,password,other_fields)**
接受username field和required字段来创建superuser。例如,如果使用email作为username field, date_of_birth作为required field:

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">def <code class="python plain">create_superuser(<code class="python color1">self<code class="python plain">,password):


<div class="line number2 index1 alt1"><code class="python spaces"><code class="python comments"># create superuser here

<div class="line number3 index2 alt2"><code class="python spaces"><code class="python plain">...

</td>

</tr>

</table>

create_superuser中的password是必需的

4.扩展Django默认的User

如果你完全满意Django的用户模型和你只是想添加一些额外的属性信息,你只需继承 django.contrib.auth.models.AbstractUser 然后添加自定义的属性。AbstractUser 作为一个抽象模型提供了默认的User的所有的实现(AbstractUser provides the full implementation of the default User as an abstract model.)。

5.自定义用户与内置身份验证表单

Django内置的forms和views和相关联的user model有一些先决条件。如果你的user model没有遵循同样的条件,则需要定义一个替代的form,通过form成为身份验证views配置的一部分。

UserCreationForm
依赖于User Model. 扩展User时必须重写。

UserChangeForm
依赖于User Model. 扩展User时必须重写。

AuthenticationForm
Works with any subclass of AbstractBaseUser,and will adapt to use the field defined in USERNAME_FIELD.

PasswordResetForm
Assumes that the user model has a field named email that can be used to identify the user and a boolean field named is_active to prevent password resets for inactive users.

SetPasswordForm
Works with 任何AbstractBaseUser子类

PasswordChangeForm
Works with 任何AbstractBaseUser子类

AdminPasswordChangeForm
Works with 任何AbstractBaseUser子类

6.自定义用户和django.contrib.admin

如果你想让你自定义的User模型也可以在站点管理上工作,那么你的模型应该再定义一些额外的属性和方法。 这些方法允许管理员去控制User到管理内容的访问:

is_staff
是否允许user访问admin界面

is_active
用户是否活跃。

has_perm(perm,obj=None):
user是否拥有perm权限。

has_module_perms(app_label):
user是否拥有app中访问models的权限

你同样也需要注册你自定义的用户模型到admin。如果你的自定义用户模型扩展于django.contrib.auth.models.AbscustomauthtractUser,你可以用django的 django.contrib.auth.admin.UserAdmin 类。如果你的用户模型扩展于 AbstractBaseUser,你需要自定义一个ModelAdmin类。他可能继承于默认的django.contrib.auth.admin.UserAdmin。然而,你也需要覆写一些django.contrib.auth.models.AbstractUser 字段的定义不在你自定义用户模型中的。

7.自定义用户和权限

如果想让在自定义用户模型中包含Django的权限控制框架变得简单,Django提供了PermissionsMixin。这是一个抽象的类,你可以为你的自定义用户模型中的类的层次结构中包含它。它提供给你所有Django权限类所必须的的方法和字段

7.1 如果要定制User的权限系统,最简单的方法是继承PermissionsMixin

源码:

</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="python keyword">class <code class="python plain">PermissionsMixin(models.Model):


<div class="line number2 index1 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number3 index2 alt2"><code class="python spaces"><code class="python comments">A mixin class that adds the fields and methods necessary to support

<div class="line number4 index3 alt1"><code class="python spaces"><code class="python comments">Django's Group and Permission model using the ModelBackend.

<div class="line number5 index4 alt2"><code class="python spaces"><code class="python comments">"""

<div class="line number6 index5 alt1"><code class="python spaces"><code class="python plain">issuperuser <code class="python keyword">= <code class="python plain">models.BooleanField((<code class="python string">'superuser status'<code class="python plain">),default<code class="python keyword">=<code class="python color1">False<code class="python plain">,

<div class="line number7 index6 alt2"><code class="python spaces"><code class="python plain">helptext<code class="python keyword">=<code class="python plain">(<code class="python string">'Designates that this user has all permissions without '

<div class="line number8 index7 alt1"><code class="python spaces"><code class="python string">'explicitly assigning them.'<code class="python plain">))

<div class="line number9 index8 alt2"><code class="python spaces"><code class="python plain">groups <code class="python keyword">= <code class="python plain">models.ManyToManyField(Group,verbosename<code class="python keyword">=<code class="python plain">(<code class="python string">'groups'<code class="python plain">),

<div class="line number10 index9 alt1"><code class="python spaces"><code class="python plain">blank<code class="python keyword">=<code class="python color1">True<code class="python plain">,helptext<code class="python keyword">=<code class="python plain">(<code class="python string">'The groups this user belongs to. A user will '

<div class="line number11 index10 alt2"><code class="python spaces"><code class="python string">'get all permissions granted to each of '

<div class="line number12 index11 alt1"><code class="python spaces"><code class="python string">'their groups.'<code class="python plain">),

<div class="line number13 index12 alt2"><code class="python spaces"><code class="python plain">related_name<code class="python keyword">=<code class="python string">"user_set"<code class="python plain">,related_query_name<code class="python keyword">=<code class="python string">"user"<code class="python plain">)

<div class="line number14 index13 alt1"><code class="python spaces"><code class="python plain">user_permissions <code class="python keyword">= <code class="python plain">models.ManyToManyField(Permission,

<div class="line number15 index14 alt2"><code class="python spaces"><code class="python plain">verbosename<code class="python keyword">=<code class="python plain">(<code class="python string">'user permissions'<code class="python plain">),blank<code class="python keyword">=<code class="python color1">True<code class="python plain">,

<div class="line number16 index15 alt1"><code class="python spaces"><code class="python plain">helptext<code class="python keyword">=<code class="python plain">(<code class="python string">'Specific permissions for this user.'<code class="python plain">),

<div class="line number17 index16 alt2"><code class="python spaces"><code class="python plain">related_name<code class="python keyword">=<code class="python string">"user_set"<code class="python plain">,related_query_name<code class="python keyword">=<code class="python string">"user"<code class="python plain">)

<div class="line number18 index17 alt1">

<div class="line number19 index18 alt2"><code class="python spaces"><code class="python keyword">class <code class="python plain">Meta:

<div class="line number20 index19 alt1"><code class="python spaces"><code class="python plain">abstract <code class="python keyword">= <code class="python color1">True

<div class="line number21 index20 alt2">

<div class="line number22 index21 alt1"><code class="python spaces"><code class="python keyword">def <code class="python plain">get_group_permissions(<code class="python color1">self<code class="python plain">,obj<code class="python keyword">=<code class="python color1">None<code class="python plain">):

<div class="line number23 index22 alt2"><code class="python spaces"><code class="python comments">"""

<div class="line number24 index23 alt1"><code class="python spaces"><code class="python comments">Returns a list of permission strings that this user has through their

<div class="line number25 index24 alt2"><code class="python spaces"><code class="python comments">groups. This method queries all available auth backends. If an object

<div class="line number26 index25 alt1"><code class="python spaces"><code class="python comments">is passed in,only permissions matching this object are returned.

<div class="line number27 index26 alt2"><code class="python spaces"><code class="python comments">"""

<div class="line number28 index27 alt1"><code class="python spaces"><code class="python plain">permissions <code class="python keyword">= <code class="python functions">set<code class="python plain">()

<div class="line number29 index28 alt2"><code class="python spaces"><code class="python keyword">for <code class="python plain">backend <code class="python keyword">in <code class="python plain">auth.get_backends():

<div class="line number30 index29 alt1"><code class="python spaces"><code class="python keyword">if <code class="python functions">hasattr<code class="python plain">(backend,<code class="python string">"get_group_permissions"<code class="python plain">):

<div class="line number31 index30 alt2"><code class="python spaces"><code class="python plain">permissions.update(backend.get_group_permissions(<code class="python color1">self<code class="python plain">,obj))

<div class="line number32 index31 alt1"><code class="python spaces"><code class="python keyword">return <code class="python plain">permissions

<div class="line number33 index32 alt2">

<div class="line number34 index33 alt1"><code class="python spaces"><code class="python keyword">def <code class="python plain">get_all_permissions(<code class="python color1">self<code class="python plain">,obj<code class="python keyword">=<code class="python color1">None<code class="python plain">):

<div class="line number35 index34 alt2"><code class="python spaces"><code class="python keyword">return <code class="python plain">_user_get_all_permissions(<code class="python color1">self<code class="python plain">,obj)

<div class="line number36 index35 alt1">

<div class="line number37 index36 alt2"><code class="python spaces"><code class="python keyword">def <code class="python plain">has_perm(<code class="python color1">self<code class="python plain">,perm,obj<code class="python keyword">=<code class="python color1">None<code class="python plain">):

<div class="line number38 index37 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number39 index38 alt2"><code class="python spaces"><code class="python comments">Returns True if the user has the specified permission. This method

<div class="line number40 index39 alt1"><code class="python spaces"><code class="python comments">queries all available auth backends,but returns immediately if any

<div class="line number41 index40 alt2"><code class="python spaces"><code class="python comments">backend returns True. Thus,a user who has permission from a single

<div class="line number42 index41 alt1"><code class="python spaces"><code class="python comments">auth backend is assumed to have permission in general. If an object is

<div class="line number43 index42 alt2"><code class="python spaces"><code class="python comments">provided,permissions for this specific object are checked.

<div class="line number44 index43 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number45 index44 alt2">

<div class="line number46 index45 alt1"><code class="python spaces"><code class="python comments"># Active superusers have all permissions.

<div class="line number47 index46 alt2"><code class="python spaces"><code class="python keyword">if <code class="python color1">self<code class="python plain">.is_active <code class="python keyword">and <code class="python color1">self<code class="python plain">.is_superuser:

<div class="line number48 index47 alt1"><code class="python spaces"><code class="python keyword">return <code class="python color1">True

<div class="line number49 index48 alt2">

<div class="line number50 index49 alt1"><code class="python spaces"><code class="python comments"># Otherwise we need to check the backends.

<div class="line number51 index50 alt2"><code class="python spaces"><code class="python keyword">return <code class="python plain">_user_has_perm(<code class="python color1">self<code class="python plain">,obj)

<div class="line number52 index51 alt1">

<div class="line number53 index52 alt2"><code class="python spaces"><code class="python keyword">def <code class="python plain">has_perms(<code class="python color1">self<code class="python plain">,perm_list,obj<code class="python keyword">=<code class="python color1">None<code class="python plain">):

<div class="line number54 index53 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number55 index54 alt2"><code class="python spaces"><code class="python comments">Returns True if the user has each of the specified permissions. If

<div class="line number56 index55 alt1"><code class="python spaces"><code class="python comments">object is passed,it checks if the user has all required perms for this

<div class="line number57 index56 alt2"><code class="python spaces"><code class="python comments">object.

<div class="line number58 index57 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number59 index58 alt2"><code class="python spaces"><code class="python keyword">for <code class="python plain">perm <code class="python keyword">in <code class="python plain">perm_list:

<div class="line number60 index59 alt1"><code class="python spaces"><code class="python keyword">if <code class="python keyword">not <code class="python color1">self<code class="python plain">.has_perm(perm,obj):

<div class="line number61 index60 alt2"><code class="python spaces"><code class="python keyword">return <code class="python color1">False

<div class="line number62 index61 alt1"><code class="python spaces"><code class="python keyword">return <code class="python color1">True

<div class="line number63 index62 alt2">

<div class="line number64 index63 alt1"><code class="python spaces"><code class="python keyword">def <code class="python plain">has_module_perms(<code class="python color1">self<code class="python plain">,app_label):

<div class="line number65 index64 alt2"><code class="python spaces"><code class="python comments">"""

<div class="line number66 index65 alt1"><code class="python spaces"><code class="python comments">Returns True if the user has any permissions in the given app label.

<div class="line number67 index66 alt2"><code class="python spaces"><code class="python comments">Uses pretty much the same logic as has_perm,above.

<div class="line number68 index67 alt1"><code class="python spaces"><code class="python comments">"""

<div class="line number69 index68 alt2"><code class="python spaces"><code class="python comments"># Active superusers have all permissions.

<div class="line number70 index69 alt1"><code class="python spaces"><code class="python keyword">if <code class="python color1">self<code class="python plain">.is_active <code class="python keyword">and <code class="python color1">self<code class="python plain">.is_superuser:

<div class="line number71 index70 alt2"><code class="python spaces"><code class="python keyword">return <code class="python color1">True

<div class="line number72 index71 alt1">

<div class="line number73 index72 alt2"><code class="python spaces"><code class="python keyword">return <code class="python plain">_user_has_module_perms(<code class="python color1">self<code class="python plain">,app_label)

</td>

</tr>

</table>

4.3.2 Django内置的User对象就继承了AbstractBaseUser和PermissionsMixin:

源码:

An - username = models.CharField(_(),max_length=,unique==_( = ),=: _(= models.CharField(_(),blank== models.CharField(_(),blank== models.EmailField(_(),blank== models.BooleanField(_(),==_( = models.BooleanField(_(),==_( = models.DateTimeField(_(),=objects </span>=<span style="color: #000000;"&gt; UserManager() USERNAME_FIELD </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;username</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt; REQUIRED_FIELDS </span>= [<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;] </span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; Meta: verbose_name </span>= _(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;user</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;) verbose_name_plural </span>= _(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;users</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;) </span><span style="color: #0000ff;"&gt;abstract</span> =<span style="color: #000000;"&gt; True def get_full_name(self): </span><span style="color: #800000;"&gt;"""

Returns the first_name plus the last_name,with a space <span style="color: #0000ff;">in<span style="color: #000000;"> between.
<span style="color: #800000;">"""
full_name = <span style="color: #800000;">'<span style="color: #800000;">%s %s<span style="color: #800000;">' %<span style="color: #000000;"> (self.first_name,self.last_name)
<span style="color: #0000ff;">return<span style="color: #000000;"> full_name.strip()

def get_short_name(self):
    </span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Returns the short name for the user.</span><span style="color: #800000;"&gt;"</span>
    <span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.first_name

def email_user(self,subject,message,from_email</span>=None,**<span style="color: #000000;"&gt;kwargs):
    </span><span style="color: #800000;"&gt;"""

Sends an email to <span style="color: #0000ff;">this<span style="color: #000000;"> User.
<span style="color: #800000;">"""
send_mail(subject,from_email,[self.email],**<span style="color: #000000;">kwargs)

<span style="color: #0000ff;">class<span style="color: #000000;"> User(AbstractUser):
<span style="color: #800000;">"""
Users within the Django authentication system are represented by <span style="color: #0000ff;">this<span style="color: #000000;">
model.
Username,password and email are required. Other fields are optional.
<span style="color: #800000;">"""
<span style="color: #0000ff;">class<span style="color: #000000;"> Meta(AbstractUser.Meta):
swappable = <span style="color: #800000;">'<span style="color: #800000;">AUTH_USER_MODEL<span style="color: #800000;">'

4.3.3 PermissionsMixin提供的这些方法和属性:

is_superuser
布尔类型。 Designates that this user has all permissions without explicitly assigning them.

get_group_permissions(obj=None)
Returns a set of permission strings that the user has,through their groups.

If obj is passed in,only returns the group permissions for this specific object.

get_all_permissions(obj=None)
Returns a set of permission strings that the user has,both through group and user permissions.

If obj is passed in,only returns the permissions for this specific object.

has_perm(perm,obj=None)
Returns True if the user has the specified permission,where perm is in the format "." (see permissions). If the user is inactive,this method will always return False.

If obj is passed in,this method won’t check for a permission for the model,but for this specific object.

has_perms(perm_list,obj=None)
Returns True if the user has each of the specified permissions,where each perm is in the format ".". If the user is inactive,this method won’t check for permissions for the model,but for the specific object.

has_module_perms(package_name)
Returns True if the user has any permissions in the given package (the Django app label). If the user is inactive,this method will always return False.

5.官方提供的一个完整的例子

这是一个管理器允许的自定义user这个用户模型使用邮箱地址作为用户名,并且要求填写出生年月。it provides no permission checking,beyond a simple admin flag on the user account. This model would be compatible with all the built-in auth forms and views,except for the User creation forms. This example illustrates how most of the components work together,but is not intended to be copied directly into projects for production use.

<span style="color: #0000ff;">from<span style="color: #000000;"> django.db import models
<span style="color: #0000ff;">from<span style="color: #000000;"> django.contrib.auth.models import (
BaseUserManager,AbstractBaseUser
)

<span style="color: #0000ff;">class<span style="color: #000000;"> MyUserManager(BaseUserManager):
def create_user(self,password=<span style="color: #000000;">None):
<span style="color: #800000;">"""
<span style="color: #000000;"> Creates and saves a User with the given email,date of
birth and password.
<span style="color: #800000;">"""
<span style="color: #0000ff;">if<span style="color: #000000;"> not email:
raise ValueError(<span style="color: #800000;">'<span style="color: #800000;">Users must have an email address<span style="color: #800000;">'<span style="color: #000000;">)

    user </span>=<span style="color: #000000;"&gt; self.model(
        email</span>=<span style="color: #000000;"&gt;self.normalize_email(email),date_of_birth</span>=<span style="color: #000000;"&gt;date_of_birth,)

    user.set_password(password)
    user.save(</span><span style="color: #0000ff;"&gt;using</span>=<span style="color: #000000;"&gt;self._db)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; user

def create_superuser(self,password):
    </span><span style="color: #800000;"&gt;"""

<span style="color: #000000;"> Creates and saves a superuser with the given email,date of
birth and password.
<span style="color: #800000;">"""
user =<span style="color: #000000;"> self.create_user(email,password=<span style="color: #000000;">password,date_of_birth=<span style="color: #000000;">date_of_birth
)
user.is_admin =<span style="color: #000000;"> True
user.save(<span style="color: #0000ff;">using=<span style="color: #000000;">self._db)
<span style="color: #0000ff;">return<span style="color: #000000;"> user

<span style="color: #0000ff;">class<span style="color: #000000;"> MyUser(AbstractBaseUser):
email =<span style="color: #000000;"> models.EmailField(
verbose_name=<span style="color: #800000;">'<span style="color: #800000;">email address<span style="color: #800000;">'<span style="color: #000000;">,max_length=<span style="color: #800080;">255<span style="color: #000000;">,unique=<span style="color: #000000;">True,)
date_of_birth =<span style="color: #000000;"> models.DateField()
is_active = models.BooleanField(<span style="color: #0000ff;">default=<span style="color: #000000;">True)
is_admin = models.BooleanField(<span style="color: #0000ff;">default=<span style="color: #000000;">False)

objects </span>=<span style="color: #000000;"&gt; MyUserManager()

USERNAME_FIELD </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;
REQUIRED_FIELDS </span>= [<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;date_of_birth</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;]

def get_full_name(self):
    # The user </span><span style="color: #0000ff;"&gt;is</span><span style="color: #000000;"&gt; identified by their email address
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.email

def get_short_name(self):
    # The user </span><span style="color: #0000ff;"&gt;is</span><span style="color: #000000;"&gt; identified by their email address
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.email

def __str__(self):              # __unicode__ on Python </span><span style="color: #800080;"&gt;2</span>
    <span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; self.email

def has_perm(self,obj</span>=<span style="color: #000000;"&gt;None):
    </span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Does the user have a specific permission?</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
    # Simplest possible answer: Yes,always
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; True

def has_module_perms(self,app_label):
    </span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Does the user have permissions to view the app `app_label`?</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
    # Simplest possible answer: Yes,always
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; True

@property
def is_staff(self):
    </span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Is the user a member of staff?</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
    # Simplest possible answer: All admins are staff
    </span><span style="color: #0000ff;"&gt;return</span> self.is_admin</pre>

可以看到manager定义了create_user()和create_superuser()方法,MyUser定义了USERNAME_FIELD,REQUIRED_FIELDS字段和get_full_name(),get_short_name()方法,为了能与admin一起使用,还定义了is_active,has_perm(),has_module_perms()

要在admin中注册自定义的MyUser,还需要在app的admin.py中重写UserCreationForm和UserChangeForm:

<span style="color: #0000ff;">from<span style="color: #000000;"> customauth.models import MyUser

<span style="color: #0000ff;">class<span style="color: #000000;"> UserCreationForm(forms.ModelForm):
<span style="color: #800000;">"""<span style="color: #800000;">A form for creating new users. Includes all the required
fields,plus a repeated password.<span style="color: #800000;">"""
password1 = forms.CharField(label=<span style="color: #800000;">'<span style="color: #800000;">Password<span style="color: #800000;">',widget=<span style="color: #000000;">forms.PasswordInput)
password2 = forms.CharField(label=<span style="color: #800000;">'<span style="color: #800000;">Password confirmation<span style="color: #800000;">',widget=<span style="color: #000000;">forms.PasswordInput)

</span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; Meta:
    model </span>=<span style="color: #000000;"&gt; MyUser
    fields </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;date_of_birth</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)

def clean_password2(self):
    # Check that the two password entries match
    password1 </span>= self.cleaned_data.<span style="color: #0000ff;"&gt;get</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;password1</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
    password2 </span>= self.cleaned_data.<span style="color: #0000ff;"&gt;get</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;password2</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;if</span> password1 and password2 and password1 !=<span style="color: #000000;"&gt; password2:
        raise forms.ValidationError(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Passwords don't match</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; password2

def save(self,commit</span>=<span style="color: #000000;"&gt;True):
    # Save the provided password </span><span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; hashed format
    user </span>= super(UserCreationForm,self).save(commit=<span style="color: #000000;"&gt;False)
    user.set_password(self.cleaned_data[</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;password1</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;])
    </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; commit:
        user.save()
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; user

<span style="color: #0000ff;">class<span style="color: #000000;"> UserChangeForm(forms.ModelForm):
<span style="color: #800000;">"""<span style="color: #800000;">A form for updating users. Includes all the fields on
the user,but replaces the password field with admin<span style="color: #800000;">'<span style="color: #800000;">s
<span style="color: #000000;"> password hash display field.
<span style="color: #800000;">"""
password =<span style="color: #000000;"> ReadOnlyPasswordHashField()

</span><span style="color: #0000ff;"&gt;class</span><span style="color: #000000;"&gt; Meta:
    model </span>=<span style="color: #000000;"&gt; MyUser
    fields </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;password</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;date_of_birth</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;is_active</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;is_admin</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)

def clean_password(self):
    # Regardless of what the user provides,</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; the initial value.
    # This </span><span style="color: #0000ff;"&gt;is</span><span style="color: #000000;"&gt; done here,rather than on the field,because the
    # field does not have access to the initial value
    </span><span style="color: #0000ff;"&gt;return</span> self.initial[<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;password</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;]

<span style="color: #0000ff;">class<span style="color: #000000;"> MyUserAdmin(UserAdmin):

The forms to add and change user instances

form </span>=<span style="color: #000000;"&gt; UserChangeForm
add_form </span>=<span style="color: #000000;"&gt; UserCreationForm

# The fields to be used </span><span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; displaying the User model.
# These </span><span style="color: #0000ff;"&gt;override</span> the definitions on the <span style="color: #0000ff;"&gt;base</span><span style="color: #000000;"&gt; UserAdmin
# that reference specific fields on auth.User.
list_display </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;is_admin</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)
list_filter </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;is_admin</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,)
fieldsets </span>=<span style="color: #000000;"&gt; (
    (None,{</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;fields</span><span style="color: #800000;"&gt;'</span>: (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;password</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)}),(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;Personal info</span><span style="color: #800000;"&gt;'</span>,{<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;fields</span><span style="color: #800000;"&gt;'</span>: (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;date_of_birth</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,)}),(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;Permissions</span><span style="color: #800000;"&gt;'</span>,{<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;fields</span><span style="color: #800000;"&gt;'</span>: (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;is_admin</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,)
# add_fieldsets </span><span style="color: #0000ff;"&gt;is</span><span style="color: #000000;"&gt; not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use </span><span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt; attribute when creating a user.
add_fieldsets </span>=<span style="color: #000000;"&gt; (
    (None,{
        </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;classes</span><span style="color: #800000;"&gt;'</span>: (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;wide</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,),</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;fields</span><span style="color: #800000;"&gt;'</span>: (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;password1</span><span style="color: #800000;"&gt;'</span>,<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;password2</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)}
    ),)
search_fields </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,)
ordering </span>= (<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;email</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,)
filter_horizontal </span>=<span style="color: #000000;"&gt; ()

Now register the <span style="color: #0000ff;">new<span style="color: #000000;"> UserAdmin...

admin.site.register(MyUser,MyUserAdmin)

... and,since we<span style="color: #800000;">'<span style="color: #800000;">re not using Django<span style="color: #800000;">'s built-<span style="color: #0000ff;">in<span style="color: #000000;"> permissions,# unregister the Group model <span style="color: #0000ff;">from<span style="color: #000000;"> admin.

admin.site.unregister(Group)

最后,别忘了在settings.py中定义AUTH_USER_MODEL:

作者:常大鹏链接:http://www.jianshu.com/p/b993f4feff83來源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

转:https://www.cnblogs.com/robinunix/p/7922403.html#_lab2_0_7

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!