基本上在任何網站上,都無可避免的須要設計實現網站的用戶系統。此時咱們須要實現包括用戶註冊、用戶登陸、用戶認證、註銷、修改密碼等功能。 使用Django,咱們能夠不須要本身寫這些功能,由於Django內置了強大的用戶認證系統--auth,它默認使用 auth_user 表來存儲用戶數據。 from django.contrib import auth # 使用auth認證系統
from django.contrib.auth.models import User # auth認證系統默認使用User表 注意:命令行建立超級用戶 python manage.py createsuperuser
提供了用戶認證功能,即驗證用戶名以及密碼是否正確,通常須要username 、password兩個關鍵字參數。
若是認證成功(用戶名和密碼正確有效),便會返回一個 User 對象。
authenticate()會在該 User 對象上設置一個屬性(id)來標識後端已經認證了該用戶,且該信息在後續的登陸過程當中是須要的。
用法:
from django.contrib import auth
user_obj = auth.authenticate(username=username,password=pwd)
該函數接受一個HttpRequest對象,以及一個通過認證的User對象。 該函數實現一個用戶登陸的功能。它本質上會在後端爲該用戶生成相關session數據。 用法:auth.login(request, user_obj) 示例: from django.shortcuts import render, HttpResponse, redirect from django.contrib import auth def login(request): if request.method == "POST": username = request.POST.get('username') pwd = request.POST.get('password') # 調用auth模塊的認證方法,判斷用戶名和密碼是否正確,正確返回一個user_obj user_obj = auth.authenticate(username=username, password=pwd) if user_obj: # 登陸成功,設置Session數據 auth.login(request, user_obj) return HttpResponse('登陸成功') else: return render(request, 'login.html', {'error_msg': '用戶名或者密碼錯誤'}) return render(request, 'login.html') 注意: 只要使用login(request, user_obj)以後,request.user就能拿到當前登陸的用戶對象。不然request.user獲得的是一個匿名用戶對象(AnonymousUser Object)。 詳細原理請查看 AuthenticationMiddleware 中間件源碼。
該函數接受一個HttpRequest對象,無返回值。 當調用該函數時,當前請求的session信息會所有清除。該用戶即便沒有登陸,使用該函數也不會報錯。 用法: from django.contrib import auth def logout(request): auth.logout(request) return redirect('/login/')
auth 給咱們提供的一個裝飾器工具,用來快捷的給某個視圖添加登陸校驗。 用法: from django.contrib.auth.decorators import login_required @login_required def index(request): return render(request, 'index.html') 若用戶沒有登陸,則會跳轉到django默認的登陸URL '/accounts/login/ ' 並傳遞當前訪問url的絕對路徑 (登錄成功後,會重定向到該路徑)。 若是須要自定義登陸的URL,則須要在settings.py文件中經過LOGIN_URL進行修改。 示例: LOGIN_URL = '/login/' # 這裏配置成你項目登陸頁面的路由
auth 提供的一個建立新用戶的方法,須要提供必要參數(username、password)等。 用法: from django.contrib.auth.models import User user = User.objects.create_user(username='用戶名',password='密碼',email='郵箱',...) 示例: def reg(request): if request.method == 'POST': username = request.POST.get('username') pwd = request.POST.get('password') # 假設數據都通過有效性校驗了 # 去數據庫建立一條記錄 User.objects.create_user(username=username, password=pwd) # create_user建立普通用戶 # User.objects.create_superuser(username=username, password=pwd) # create_superuser建立超級用戶 # 建立成功,跳轉登陸頁年 return redirect('/login/') return render(request, 'reg.html')
auth 提供的一個建立新的超級用戶的方法,須要提供必要參數(username、password)等。 用法: from django.contrib.auth.models import User user_obj = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)
auth 提供的一個檢查密碼是否正確的方法,須要提供當前請求用戶的密碼。 密碼正確返回True,不然返回False。 用法: ok = user_obj.check_password('密碼') 或者直接針對當前請求的user對象校驗原密碼是否正確: ok = request.user.check_password(raw_password='原密碼')
auth 提供的一個修改密碼的方法,接收要設置的新密碼 做爲參數。 注意:設置完必定要調用用戶對象的save方法!!! 用法: user_obj.set_password('新密碼') user_obj.save()
用來判斷當前請求是否經過了認證。 用法: def my_view(request): if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
從user_obj = request.user能夠拿到當前登陸的用戶對象,用戶對象user_obj可以拿到認證所用用戶表的數據屬性,好比username, password等。
其餘經常使用屬性含義以下:
is_staff : 用戶是否擁有網站的管理權限.
is_active : 是否容許用戶登陸, 設置爲 False,能夠在不刪除用戶的前提下禁止用戶登陸。
1、介紹 雖然內置的認證系統很好用,可是auth_user表字段都是固定的那幾個,若是我想要加一個存儲用戶手機號的字段怎麼辦? 方法一:新建另一張表而後經過一對一和內置的auth_user表關聯 方法二:經過繼承內置的AbstractUser類,來定義一個本身的Model類。 這樣既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統了。 2、示例: models.py from django.db import models from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): # 這裏定義拓展的字段 gender = models.PositiveIntegerField(choices=((0, '女'),(1, '男'), (2, '保密'))) phone = models.CharField(max_length=11) 3、注意: 按上面的方式擴展了內置的auth_user表以後,必定要在settings.py中告訴Django,我如今使用我新定義的UserInfo表來作用戶認證。寫法以下: # 引用Django自帶的User表,繼承使用時須要設置 AUTH_USER_MODEL = "app名.UserInfo" 4、自定義認證系統默認使用的數據表以後,咱們就能夠像使用默認的auth_user表那樣使用咱們的UserInfo表了。好比: 建立普通用戶: UserInfo.objects.create_user(username='用戶名', password='密碼') 建立超級用戶: UserInfo.objects.create_superuser(username='用戶名', password='密碼') 5、再次注意: 一旦咱們指定了新的認證系統所使用的表,咱們就須要從新在數據庫中建立該表,而不能繼續使用原來默認的auth_user表了。 默認的auth_user表就會被你自定義的表替代,即auth_user表不存在了,咱們使用auth模塊的方法,修改的就是新的表。 繼承AbstractUser是在User表的基礎上拓展字段,User表原來的字段仍是有的,可是若是我就不想要User表的某些字段,並且還要拓展我須要的字段呢? 怎麼辦?就須要繼承AbstractBaseUser, PermissionsMixin重寫一個表,表內的字段徹底是你設計的字段
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager # 定義UserProfile這個類的管理類 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_staff', False) # 給字典設置默認值 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_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=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) class UserProfile(AbstractBaseUser, PermissionsMixin): email = models.EmailField( max_length=255, unique=True, validators=[RegexValidator(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$', '郵箱格式不正確'),] ) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_('Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( _('active'), default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) name = models.CharField('名字', max_length=32) department = models.ForeignKey('Department', default=None, blank=True, null=True) mobile = models.CharField( '手機', max_length=32, default=None, blank=True, null=True, validators=[RegexValidator(r'^1[3-9]\d{9}$', '手機格式不正確')] ) memo = models.TextField('備註', blank=True, null=True, default=None) date_joined = models.DateTimeField(auto_now_add=True) EMAIL_FIELD = 'email' # 發送郵件的字段 USERNAME_FIELD = 'email' # 用來惟一肯定auth中的用戶 REQUIRED_FIELDS = ['name'] # auth指定除了上面兩個配置項的字段還有哪些字段須要必填 class Meta: verbose_name = '帳戶信息' verbose_name_plural = "帳戶信息" def clean(self): super(UserProfile, self).clean() # 對郵件進行校驗 self.email = self.__class__.objects.normalize_email(self.email) def get_full_name(self): # The user is identified by their email address return self.name def get_short_name(self): # The user is identified by their email address return self.email def __str__(self): # __unicode__ on Python 2 return self.name # 給ORM添加管理類 objects = UserManager()
@login_required def set_password(request): user = request.user err_msg = '' if request.method == 'POST': old_password = request.POST.get('old_password') new_password = request.POST.get('new_password') re_password = request.POST.get('re_password') # 檢查舊密碼是否正確 if user.check_password(old_password): if not new_password: err_msg = '新密碼不能爲空' elif new_password != re_password: err_msg = '兩次密碼不一致' else: user.set_password(new_password) user.save() return redirect("/login/") else: err_msg = '原密碼輸入錯誤' return render(request, 'set_password.html', {'err_msg': err_msg})