8.2 django User模型

User模型

User模型是這個框架的核心部分。他的完整的路徑是在django.contrib.auth.models.User。以下對這個User對象做一個簡單了解:

字段:

內置的User模型擁有以下的字段:

  1. username: 用戶名。150個字符以內。可以包含數字和英文字符,以及_@+.-字符。不能為空,且必須唯一!
  2. first_name:歪果仁的first_name,在30個字符以內。可以為空。
  3. last_name:歪果仁的last_name,在150個字符以內。可以為空。
  4. email:郵箱。可以為空。
  5. password:密碼。經過哈希過后的密碼。
  6. groups:分組。一個用戶可以屬于多個分組,一個分組可以擁有多個用戶。groups這個字段是跟Group的一個多對多的關系。
  7. user_permissions:權限。一個用戶可以擁有多個權限,一個權限可以被多個用戶所有用。和Permission屬于一種多對多的關系。
  8. is_staff:是否可以進入到admin的站點。代表是否是員工。
  9. is_active:是否是可用的。對于一些想要刪除賬號的數據,我們設置這個值為False就可以了,而不是真正的從數據庫中刪除。
  10. is_superuser:是否是超級管理員。如果是超級管理員,那么擁有整個網站的所有權限。
  11. last_login:上次登錄的時間。
  12. date_joined:賬號創建的時間。

User模型的基本用法:

創建用戶:

通過create_user方法可以快速的創建用戶。這個方法必須要傳遞usernameemailpassword。示例代碼如下:

from django.contrib.auth.models import User
user = User.objects.create_user('zhiliao','hynever@zhiliao.com','111111')
# 此時user對象已經存儲到數據庫中了。當然你還可以繼續使用user對象進行一些修改
user.last_name = 'abc'
user.save()

創建超級用戶:

創建超級用戶有兩種方式。第一種是使用代碼的方式。用代碼創建超級用戶跟創建普通用戶非常的類似,只不過是使用create_superuser。示例代碼如下:

from django.contrib.auth.models import User
User.objects.create_superuser('admin','admin@163.com','111111')

也可以通過命令行的方式。命令如下:

python manage.py createsuperuser

后面就會提示你輸入用戶名、郵箱以及密碼。

修改密碼:

因為密碼是需要經過加密后才能存儲進去的。所以如果想要修改密碼,不能直接修改password字段,而需要通過調用set_password來達到修改密碼的目的。示例代碼如下:

from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.set_password('新的密碼')
user.save()

登錄驗證:

Django的驗證系統已經幫我們實現了登錄驗證的功能。通過django.contrib.auth.authenticate即可實現。這個方法只能通過usernamepassword來進行驗證。示例代碼如下:

from django.contrib.auth import authenticate
user = authenticate(username='zhiliao', password='111111')
# 如果驗證通過了,那么就會返回一個user對象。
if user is not None:
    # 執行驗證通過后的代碼
else:
    # 執行驗證沒有通過的代碼。

擴展用戶模型:

Django內置的User模型雖然已經足夠強大了。但是有時候還是不能滿足我們的需求。比如在驗證用戶登錄的時候,他用的是用戶名作為驗證,而我們有時候需要通過手機號碼或者郵箱來進行驗證。還有比如我們想要增加一些新的字段。那么這時候我們就需要擴展用戶模型了。擴展用戶模型有多種方式。這里我們來一一討論下。

1. 設置Proxy模型:

如果你對Django提供的字段,以及驗證的方法都比較滿意,沒有什么需要改的。但是只是需要在他原有的基礎之上增加一些操作的方法。那么建議使用這種方式。示例代碼如下:

class Person(User):
    class Meta:
        proxy = True

    def get_blacklist(self):
        return self.objects.filter(is_active=False)

在以上,我們定義了一個Person類,讓他繼承自User,并且在Meta中設置proxy=True,說明這個只是User的一個代理模型。他并不會影響原來User模型在數據庫中表的結構。以后如果你想方便的獲取所有黑名單的人,那么你就可以通過Person.get_blacklist()就可以獲取到。并且User.objects.all()Person.objects.all()其實是等價的。因為他們都是從User這個模型中獲取所有的數據。

2. 一對一外鍵:

如果你對用戶驗證方法authenticate沒有其他要求,就是使用usernamepassword即可完成。但是想要在原來模型的基礎之上添加新的字段,那么可以使用一對一外鍵的方式。示例代碼如下:

from django.contrib.auth.models import User
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save

class UserExtension(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='extension')
    birthday = models.DateField(null=True,blank=True)
    school = models.CharField(max_length=100)


@receiver(post_save,sender=User)
def create_user_extension(sender,instance,created,**kwargs):
    if created:
        UserExtension.objects.create(user=instance)
    else:
        instance.extension.save()

以上定義一個UserExtension的模型,并且讓她和User模型進行一對一的綁定,以后我們新增的字段,就添加到UserExtension上。并且還寫了一個接受保存模型的信號處理方法,只要是User調用了save方法,那么就會創建一個UserExtensionUser進行綁定。

3. 繼承自AbstractUser

對于authenticate不滿意,并且不想要修改原來User對象上的一些字段,但是想要增加一些字段,那么這時候可以直接繼承自django.contrib.auth.models.AbstractUser,其實這個類也是django.contrib.auth.models.User的父類。比如我們想要在原來User模型的基礎之上添加一個telephoneschool字段。示例代碼如下:

from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    telephone = models.CharField(max_length=11,unique=True)
    school = models.CharField(max_length=100)

    # 指定telephone作為USERNAME_FIELD,以后使用authenticate
    # 函數驗證的時候,就可以根據telephone來驗證
    # 而不是原來的username
    USERNAME_FIELD = 'telephone'
    REQUIRED_FIELDS = []

    # 重新定義Manager對象,在創建user的時候使用telephone和
    # password,而不是使用username和password
    objects = UserManager()


class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self,telephone,password,**extra_fields):
        if not telephone:
            raise ValueError("請填入手機號碼!")
        user = self.model(telephone=telephone,*extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_user(self,telephone,password,**extra_fields):
        extra_fields.setdefault('is_superuser',False)
        return self._create_user(telephone,password)

    def create_superuser(self,telephone,password,**extra_fields):
        extra_fields['is_superuser'] = True
        return self._create_user(telephone,password)

然后再在settings中配置好AUTH_USER_MODEL=youapp.User

這種方式因為破壞了原來User模型的表結構,所以必須要在第一次migrate前就先定義好。

4. 繼承自AbstractBaseUser模型:

如果你想修改默認的驗證方式,并且對于原來User模型上的一些字段不想要,那么可以自定義一個模型,然后繼承自AbstractBaseUser,再添加你想要的字段。這種方式會比較麻煩,最好是確定自己對Django比較了解才推薦使用。步驟如下:

  1. 創建模型。示例代碼如下:

     class User(AbstractBaseUser,PermissionsMixin):
         email = models.EmailField(unique=True)
         username = models.CharField(max_length=150)
         telephone = models.CharField(max_length=11,unique=True)
         is_active = models.BooleanField(default=True)
    
         USERNAME_FIELD = 'telephone'
         REQUIRED_FIELDS = []
    
         objects = UserManager()
    
         def get_full_name(self):
             return self.username
    
         def get_short_name(self):
             return self.username
    

    其中passwordlast_login是在AbstractBaseUser中已經添加好了的,我們直接繼承就可以了。然后我們再添加我們想要的字段。比如emailusernametelephone等。這樣就可以實現自己想要的字段了。但是因為我們重寫了User,所以應該盡可能的模擬User模型:

    • USERNAME_FIELD:用來描述User模型名字字段的字符串,作為唯一的標識。如果沒有修改,那么會使用USERNAME來作為唯一字段。
    • REQUIRED_FIELDS:一個字段名列表,用于當通過createsuperuser管理命令創建一個用戶時的提示。
    • is_active:一個布爾值,用于標識用戶當前是否可用。
    • get_full_name():獲取完整的名字。
    • get_short_name():一個比較簡短的用戶名。
  2. 重新定義UserManager:我們還需要定義自己的UserManager,因為默認的UserManager在創建用戶的時候使用的是usernamepassword,那么我們要替換成telephone。示例代碼如下:

     class UserManager(BaseUserManager):
         use_in_migrations = True
    
         def _create_user(self,telephone,password,**extra_fields):
             if not telephone:
                 raise ValueError("請填入手機號碼!")
             user = self.model(telephone=telephone,*extra_fields)
             user.set_password(password)
             user.save()
             return user
    
         def create_user(self,telephone,password,**extra_fields):
             extra_fields.setdefault('is_superuser',False)
             return self._create_user(telephone,password)
    
         def create_superuser(self,telephone,password,**extra_fields):
             extra_fields['is_superuser'] = True
             return self._create_user(telephone,password)
    
  3. 在創建了新的User模型后,還需要在settings中配置好。配置AUTH_USER_MODEL='appname.User'

  4. 如何使用這個自定義的模型:比如以后我們有一個Article模型,需要通過外鍵引用這個User模型,那么可以通過以下兩種方式引用。
    第一種就是直接將User導入到當前文件中。示例代碼如下:

     from django.db import models
     from myauth.models import User
     class Article(models.Model):
         title = models.CharField(max_length=100)
         content = models.TextField()
         author = models.ForeignKey(User, on_delete=models.CASCADE)
    

    這種方式是可以行得通的。但是為了更好的使用性,建議還是將User抽象出來,使用settings.AUTH_USER_MODEL來表示。示例代碼如下:

     from django.db import models
     from django.conf import settings
     class Article(models.Model):
         title = models.CharField(max_length=100)
         content = models.TextField()
         author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    

這種方式因為破壞了原來User模型的表結構,所以必須要在第一次migrate前就先定義好。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 想說卻還沒說的 還很多/攢著是因為想寫成歌/讓人輕輕地唱著 淡淡地記著/就算終于忘了 也值了/說不定我一生涓滴意念...
    寰寰小主閱讀 340評論 0 5
  • 小可愛們,最近熱播的年度鑒婊打婊大劇《知否》看了嘛? 對,就是那個李清照的那首《如夢令》,它改編成電視劇啦。 來,...
    落落晴空閱讀 310評論 0 2
  • 放著 就忘記了 不是故意的 天冷了 想起火塘 夜黑了 想起了燈光 可是 我好像忘記了什麼 把某一樣 原本屬於我的 ...
    蔡振源閱讀 238評論 0 1
  • 老夫自從用了某云音樂播放器之后,慢慢的養成了個習慣,就是每次聽歌時都去看會兒下面的評論。講真,老夫的生活從此像是吃...
    音曼實驗室閱讀 1,620評論 0 0