十七 Django-使用者模組

weixin_34148340發表於2019-02-28

一、概要

auth模組是Django提供的標準許可權管理系統,可以提供使用者身份認證, 使用者組和許可權管理

auth可以和admin模組配合使用, 快速建立網站的管理系統。

在INSTALLED_APPS中新增'django.contrib.auth'使用該app, auth模組預設啟用。

主要的操作包括:

  1. create_user 建立使用者
  2. authenticate 驗證登入
  3. login 記住使用者的登入狀態
  4. logout 退出登入
  5. is_authenticated 判斷使用者是否登入
  6. @login_required 判斷使用者是否登入的裝飾器

二、前期配置

1、說明

Django 在新建工程時已經為使用使用者認證系統做好了全部必要的配置。不過有可能你並非使用 django-admin 命令新建的工程,或者你使用的是一個正在開發中的專案,因此最好再檢查一下 settings.py 檔案中是否已經做好了全部必要配置。

2、配置

  1. 在setting.py的INSTALLED_APPS
    INSTALLED_APPS = [
        'django.contrib.auth',   
        # 使用者許可權處理部分依賴的應用    
        'django.contrib.contenttypes',
    ]
    
  2. 在setting.py的MIDDLEWARE
    MIDDLEWARE = [
    # 會話支援中介軟體
    'django.contrib.sessions.middleware.SessionMiddleware',
    # 認證支援中介軟體
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ]
    
  3. 在專案下面的urls.py中
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # 首頁
        url(r'^$', views.index, name='index')
        # 將 auth 應用中的 urls 模組包含進來
        url(r'^users/', include('django.contrib.auth.urls')),
    ]
    

三、User物件

1、user物件

  1. 屬性
    說明 說明 備註
    username 少於等於30個字元。 使用者名稱可以包含字母、數字、_、@、+、.和- 字元 必選
    first_name 少於等於30個字元 可選
    last_name 少於30個字元 可選
    email 郵箱地址 可選
    password 密碼的雜湊及後設資料。(Django 不儲存原始密碼)。原始密碼可以無限長而且可以包含任意字元。參見密碼相關的文件 必選
    groups 與Group 之間的多對多關係 可選
    user_permissions 與Permission 之間的多對多關係 可選
    is_staff 布林值。指示使用者是否可以訪問Admin 站點 可選
    is_active 布林值。指示使用者的賬號是否啟用 必選
    is_superuser 布林值。只是這個使用者擁有所有的許可權而不需要給他們分配明確的許可權。 可選
    last_login 使用者最後一次登入的時間 預設值
    date_joined 賬戶建立的時間。當賬號建立時,預設設定為當前的date/time 預設值
  2. 說明
    User 物件屬性:username, password(必填項)password用雜湊演算法儲存到資料庫
    is_staff : 使用者是否擁有網站的管理許可權.
    is_active : 是否允許使用者登入, 設定為False,可以不用刪除使用者來禁止 使用者登入

2、擴充 User 模型

2.1、說明

使用者可能還包含有頭像、暱稱、介紹等等其它屬性,因此僅僅使用 Django 內建的 User 模型是不夠。所有有些時候我們必須使用在系統的User上進行擴充

2.2、繼承AbstractUser (方式一)

  1. 說明
    推薦方式、django.contrib.auth.models.User 也是繼承自 AbstractUser 抽象基類,而且僅僅就是繼承了 AbstractUser,沒有對 AbstractUser 做任何的擴充
  2. 在app的models.py中
    class User(AbstractUser):
        # 暱稱
        nickname = models.CharField(max_length=50, blank=True)
        # 頭像
     head = models.ImageField(max_length=50)
        class Meta(AbstractUser.Meta):
            db_table='user'
            pass
    
  3. 注意
    為了讓 Django 使用者認證系統使用我們自定義的使用者模型,必須在 settings.py 裡通過 AUTH_USER_MODEL 指定自定義使用者模型所在的位置
    AUTH_USER_MODEL = '模組.User'
    
  4. 遷移
    python manage.py makemigrations
    python manage.py migrate
    

3、使用 Profile 模式(方式二)

  1. 說明
    如果想為一個已使用了 Django 內建 User 模型的專案擴充使用者模型,上述繼承 AbstractUser 的擴充方式會變得有點麻煩。Django 沒有提供將內建的 User 遷移到自定義的使用者模型,因為 Django 已經為內建的 User 模型生成了相關資料庫遷移檔案和資料庫表。如果非要這麼做的話,需要手工修改遷移檔案和資料庫表,並且移動資料庫中相關的使用者資料。
  2. 示例程式碼
    class UserProfile(models.Model):
        nickname = models.CharField(max_length=50, blank=True)
        desc = models.TextField(blank=True, null=True)
        user = models.OneToOneField(User)
    
    users = User.objects.all()
    for user in users:
       print(user.userprofile.desc)
    

4、優缺點

  1. 繼承 AbstractUser 的使用者模型只有一張資料庫表。
  2. 而 Profile 這種模式有兩張表,一張是 User 模型對應的表,一張是 Profile 模型對應的表,兩張表通過一對一的關係關聯。可見,當要查詢某個使用者的 Profile 時,需要執行額外的跨表查詢操作,所以這種方式比起直接承AbstractUser 效率更低一點。因此對於新專案來說,優先推薦使用繼承 AbstractUser 的方式來擴充使用者模型

3、 常用操作

1、驗證登入

  1. 說明
    當使用者登入的時候用authenticate(username=username,password=password)驗證登入,判斷資料庫中是否存在使用者輸入的賬號和密碼,返回一個user物件。底層將password用hash演算法加密後和資料庫中password進行對比
  2. 示例程式碼

2、註冊操作

  1. 說明
    當使用者註冊的時候用create_user(username,password,email)預設情況下is_active=True,is_staff=False,is_superuser=False
    底層將password用hash演算法加密之後儲存到資料庫中
  2. 示例程式碼
    def register_view(request):
        if request.method == 'POST':
            try:
                username = request.POST.get('username')
                password = request.POST.get('password')
                phone = request.POST.get('phone')
                email = request.POST.get('email')
                # 驗證使用者是否存在
                user = authenticate(username=username, password=password)
                if user:
                    # 使用者已經存在
                    return render(request, 'register.html', {'msg': '使用者名稱已存在'})
                else:
                    # 儲存使用者
                    user = User.objects.create_user(username=username,
                                                    password=password,
                                                    phone=phone,
                                                    email=email)
                    # 將使用者資訊儲存到session中
                    login(request, user)
                    return redirect('/')
            except Exception as e:
                return render(request, 'register.html', {'msg': '註冊失敗'})
        else:
            return render(request, 'register.html')
    

3、登入操作

  1. 說明
    當使用者登入的時候用login(request,user)來記住使用者的登入狀態
    該函式接受一個HttpRequest物件,以及一個認證了的User物件
    此函式使用django的session框架給某個已認證的使用者附加上session id等資訊。
  2. 示例程式碼
    def login_view(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
             # 驗證使用者是否存在
            user = authenticate(request, username=username, password=password)
            if user:
                 # 判斷使用者是否啟用
                if user.is_active:
                    login(request, user)
                    return redirect('/')
                else:
                    return render(request, 'test/login.html', {'msg': '使用者尚未啟用'})
            else:
                return render(request, 'test/login.html', {'msg': '使用者密碼錯誤'})
        else:
            return render(request, 'login.html')
    

4、登出操作

  1. 說明
    當使用者登出的時候用logout(request),只需要一個引數request
  2. 示例程式碼
    from django.contrib.auth import logout
    def logout_view(request):
        logout(request)
    

5、修改密碼

  1. 說明
  2. 示例程式碼
    user = auth.authenticate(username=username, password=old_password)
    if user:
        user.set_password(new_password)
        user.save()
    

6、只允許登入使用者訪問

  1. 說明
    @login_required 修飾器修飾的view函式會先通過session key檢查是否登入,
    已登入使用者可以正常的執行操作, 未登入使用者將被重定向到login_url指定的位置. 若未指定login_url引數, 則重定向到settings.LOGIN_URL
  2. 示例程式碼
    # settings 配置
    LOGIN_URL = '/user/login/'
    # views
    @login_required
    def find_user_info(request):
        pass
    
    @login_required(login_url='/accounts/login/')
    def find_user_info(request):
     pass
    

7、驗證登入

  1. 說明
    如果是真正的 User 物件,返回值恆為 True 。 用於檢查使用者是否已經通過了認證。 通過認證並不意味著使用者擁有任何許可權,甚至也不檢查該使用者是否處於啟用狀態,這只是表明使用者成功的通過了認證。 這個方法很重要, 在後臺用request.user.is_authenticated()判斷使用者是否已經登入,如果true則可以向前臺展示request.user.name
  2. 示例程式碼
    在後臺的檢視函式裡可以用request.user.is_authenticated()判斷使用者是否登入
    在前端頁面中可以用
    {% if user.is_authenticated %}
    {% endif %}
    判斷使用者是否登入
    

相關文章