欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Django的用戶模塊與權(quán)限系統(tǒng)的示例代碼

 更新時(shí)間:2019年07月24日 11:18:41   作者:EVE  
這篇文章主要介紹了Django的用戶模塊與權(quán)限系統(tǒng)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一 導(dǎo)言

設(shè)計(jì)一個(gè)好的用戶系統(tǒng)往往不是那么容易,Django提供的用戶系統(tǒng)可以快速實(shí)現(xiàn)基本的功能,并可以在此基礎(chǔ)上繼續(xù)擴(kuò)展以滿足我們的需求。

先看看Django的用戶系統(tǒng)都提供哪些功能:

  1. 提供用戶模塊(User Model)
  2. 權(quán)限驗(yàn)證(默認(rèn)添加已有模塊的增加刪除修改權(quán)限)
  3. 用戶組與組權(quán)限功能
  4. 用戶鑒權(quán)與登錄功能
  5. 與用戶登錄驗(yàn)證相關(guān)的一些函數(shù)與裝飾方法

如配置了Django的用戶系統(tǒng),僅需調(diào)用Django提供的幾個(gè)函數(shù),便可實(shí)現(xiàn)用戶的登錄,注銷,權(quán)限驗(yàn)證等功能。例如以下情景

1.登錄

# some_view.py
from django.contrib.auth import authenticate, login
 
def login(request):
  username = request.POST['username']
  password = request.POST['password']
 
  # Django提供的authenticate函數(shù),驗(yàn)證用戶名和密碼是否在數(shù)據(jù)庫(kù)中匹配
  user = authenticate(username=username, password=password)
 
  if user is not None:
    # Django提供的login函數(shù),將當(dāng)前登錄用戶信息保存到會(huì)話key中
    login(request, user)
 
    # 進(jìn)行登錄成功的操作,重定向到某處等
    ...
  else:
    # 返回用戶名和密碼錯(cuò)誤信息
    ...

2.注銷

# some_view.py
from django.contrib.auth import logout
 
def logout(request):
  # logout函數(shù)會(huì)清除當(dāng)前用戶保存在會(huì)話中的信息
  logout(request)

3.驗(yàn)證是否登錄

# some_view.py
 
def some_fuction(request):
  user = request.user
  if user.is_authenticated:
    # 已登錄用戶,可以往下進(jìn)行操作
  else:
    # 返回要求登錄信息

4.驗(yàn)證是否有權(quán)限

# some_view.py
 
def some_fuction(request):
  user = request.user
  if user.has_perm('myapp.change_bar'):
    # 有權(quán)限,可以往下進(jìn)行操作
  else:
    # 返回禁止訪問(wèn)等信息

二 用戶模塊

Django的用戶模塊類定義在auth應(yīng)用中,如要直接使用Django的用戶類,在setting配置文件中的INSTALLAPP添加一行django.contrib.auth。

這樣就可以在代碼中直接用User類創(chuàng)建用戶:

from django.contrib.auth.models import User
user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
user.last_name = 'Lennon'
user.save()

看看Django的源碼User類定義了什么屬性:

class User(AbstractUser):
  """
  Users within the Django authentication system are represented by this
  model.
  Username, password and email are required. Other fields are optional.
  """
  class Meta(AbstractUser.Meta):
    swappable = 'AUTH_USER_MODEL'

…,啥都沒(méi)有?

注意到User類繼承AbstractUser類, 用戶名和密碼信息等定義在父類了。所以再看看AbstractUser類的定義, 限于篇幅僅列出其中一部分,源碼在https://github.com/django/django/blob/master/django/contrib/auth/models.py

class AbstractUser(AbstractBaseUser, PermissionsMixin):
  username = models.CharField(
    _('username'),
    max_length=150,
    unique=True,
    help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
    validators=[username_validator],
    error_messages={
      'unique': _("A user with that username already exists."),
    },
  )
  first_name = models.CharField(_('first name'), max_length=30, blank=True)
  last_name = models.CharField(_('last name'), max_length=30, blank=True)
  email = models.EmailField(_('email address'), blank=True)
  date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
....

可以看到AbstractUser類中定義了username這個(gè)字段了,另外還有email、first_name、last_name等。AbstractUser類還繼承AbstractBaseUser和PermissionsMixin類,AbstractBaseUser類提供password字段及將密碼加密保存的相關(guān)方法,PermissionsMixin類提供User類權(quán)限認(rèn)證功能。

總的來(lái)說(shuō),一個(gè)User類,定義了以下字段:

  • username: 用戶名
  • password: 密碼
  • first_name: 姓名
  • last_name: 姓名
  • email: 郵箱
  • groups: Group類多對(duì)多的關(guān)系對(duì)象管理器
  • user_permissions: Permission類多對(duì)多的關(guān)系對(duì)象管理器
  • is_staff: 是否工作人員
  • is_active: 是否激活
  • is_superuser: 是否管理員
  • last_login: 最近登錄時(shí)間
  • date_joined: 注冊(cè)時(shí)間

另外,生成一個(gè)User實(shí)例,可以使用以下屬性:

  • is_authenticated: 只讀,用來(lái)判斷用戶是否存在。只有AnonymousUser類這個(gè)屬性為False。
  • is_anonymous: 就是用來(lái)區(qū)分 User 和 AnonymousUser 對(duì)象而已。

User類提供了許多方法方便我們執(zhí)行各種操作:

  • set_password(raw_password): 可以將password轉(zhuǎn)成hash值,記得再調(diào)用user.save()保存。
  • check_password(raw_password): 相反,將原生密碼與保存在數(shù)據(jù)庫(kù)中hash值密碼對(duì)比(直接對(duì)比肯定不相同的)。
  • has_perm(perm, obj=None),has_perms(perm_list, obj=None): 驗(yàn)證該用戶是否擁有某個(gè)權(quán)限或者權(quán)限列表
  • get_all_permissions(obj=None): 返回該用戶擁有的所有權(quán)限

三 驗(yàn)證與登錄用戶

驗(yàn)證用戶名和密碼看起來(lái)很簡(jiǎn)單,對(duì)比提交的用戶名和密碼與數(shù)據(jù)庫(kù)保存的一致即可。

如:

# some_view.py
def some_fuction(request):
  username = request.POST['username']
  password = request.POST['password']
  try:
    user = User.objects.get(username=username, password=password)
  except ObjectNotExists:
    # 用戶名和密碼不匹配一個(gè)用戶
 
  ...

由于密碼已經(jīng)進(jìn)行hash后保存,上述代碼還得先把提交的password值先hash再去數(shù)據(jù)庫(kù)中搜索,總得多寫(xiě)了一些代碼。這些Django都已經(jīng)考慮到了, 提供了一個(gè)authenticate函數(shù)驗(yàn)證是否存在該用戶,就像導(dǎo)言的實(shí)例代碼:

# some_view.py
from django.contrib.auth import authenticate, login
 
def login(request):
  username = request.POST['username']
  password = request.POST['password']
  user = authenticate(username=username, password=password)
  if user is not None:
    login(request, user)
    ...
  else:
    ...

這里重點(diǎn)說(shuō)明一下authenticate和login函數(shù)。

1.authenticate(**credentials)

傳入待驗(yàn)證的參數(shù),默認(rèn)是username和password,它會(huì)調(diào)用系統(tǒng)配置里的每一個(gè)authentication backend進(jìn)行驗(yàn)證,驗(yàn)證通過(guò)返回一個(gè)User實(shí)例,否則返回None。

每一個(gè)authentication backend指認(rèn)證后端,在setting.py中配置的AUTHENTICATION_BACKENDS變量,默認(rèn)是[‘django.contrib.auth.backends.ModelBackend'],可以增加自定義的認(rèn)證后端,或者使用第三方提供的。authenticate函數(shù)會(huì)按順序調(diào)用每一個(gè)進(jìn)行驗(yàn)證,如果第一個(gè)沒(méi)有通過(guò),它會(huì)使用第二個(gè)進(jìn)行驗(yàn)證,直到所有的認(rèn)證后端都失敗后才返回None。

看看這個(gè)ModelBackend類如何返回認(rèn)證用戶(再次縮減源碼):

class ModelBackend(object):
  def authenticate(self, request, username=None, password=None, **kwargs):
    if username is None:
      username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
      user = UserModel._default_manager.get_by_natural_key(username)
    except UserModel.DoesNotExist:
 
      UserModel().set_password(password)
    else:
      if user.check_password(password) and self.user_can_authenticate(user):
        return user
# ...

實(shí)際上authenticate函數(shù)會(huì)調(diào)用每一個(gè)authentication backend類的authenticate方法, ModelBackend類與我們之前的驗(yàn)證方法稍有不同,它先從數(shù)據(jù)庫(kù)用戶表中取出與username對(duì)應(yīng)的一個(gè)User實(shí)例,再通過(guò)User的check_password方法驗(yàn)證password是否正確,并返回這個(gè)User實(shí)例。

2.login(request, user, backend=None)

接收HttpRequest對(duì)象和一個(gè)User對(duì)象,login函數(shù)會(huì)將當(dāng)前用戶信息保存到會(huì)話cookie中,所以要使用Django用戶系統(tǒng)的所有功能,也得安裝Django默認(rèn)的會(huì)話APP。

看看login函數(shù)做了什么:

def login(request, user, backend=None):
  # (清空當(dāng)前的session信息)
  # ...
  request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
  request.session[BACKEND_SESSION_KEY] = backend
  request.session[HASH_SESSION_KEY] = session_auth_hash
  if hasattr(request, 'user'):
    request.user = user
  rotate_token(request)
  user_logged_in.send(sender=user.__class__, request=request, user=user)

login函數(shù)將當(dāng)前用戶的一個(gè)唯一標(biāo)識(shí)信息保存在request.session的SESSION_KEY中, 下次請(qǐng)求時(shí)即可從會(huì)話cookie中拿到當(dāng)前登錄的用戶對(duì)象。

如果要求登錄用戶才能訪問(wèn)相應(yīng)的View,可以這么寫(xiě):

from django.conf import settings
from django.shortcuts import redirect
 
def my_view(request):
  if not request.user.is_authenticated:
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

通過(guò)login函數(shù)可以將用戶信息保存在會(huì)話中,當(dāng)下一個(gè)請(qǐng)求到達(dá)view前,Django的會(huì)話中間件從會(huì)話cookie中取出用戶對(duì)象,并賦值給request.user。這樣,已登錄的用戶request.user.is_authenticated值為True,可以進(jìn)行相應(yīng)的操作。未登錄用戶request.user返回一個(gè)AnonymousUser對(duì)象,它的is_authenticated屬性值永遠(yuǎn)為False,那么要將這個(gè)請(qǐng)求重定向到登錄頁(yè)面。

這兩行代碼可以通過(guò)在view函數(shù)上加一個(gè)裝飾器實(shí)現(xiàn),如

@login_required
def my_view(request):
  ...

裝飾器login_required(redirect_field_name='next', login_url=None), 可傳入login_url參數(shù)設(shè)置未登錄用戶的請(qǐng)求重定向的地址,否則重定向到settings.LOGIN_URL。

四 權(quán)限認(rèn)證

User模型有兩個(gè)多對(duì)多關(guān)系的字段: groups 和 user_permissions, 它們與Pemission模型有關(guān)。User與Pemission、User與Permission、Group與Permission均是多對(duì)多關(guān)系, Permission定義了具體的權(quán)限,其字段如下:

class Permission(models.Model):
  name = models.CharField(_('name'), max_length=255)   # 權(quán)限名稱(用作顯示)
  content_type = models.ForeignKey(    # 內(nèi)容類型: 每個(gè)模型對(duì)應(yīng)一個(gè)內(nèi)容類型,用于定位指定模型
    ContentType,
    models.CASCADE,
    verbose_name=_('content type'),
  )
  codename = models.CharField(_('codename'), max_length=100)  # 權(quán)限的代碼名稱,用在如has_permission函數(shù)參數(shù)

給一個(gè)用戶添加、刪除權(quán)限很簡(jiǎn)單: myuser.user_permissions.set([permission_list]) myuser.user_permissions.add(permission, permission, …) myuser.user_permissions.remove(permission, permission, …) myuser.user_permissions.clear()

其中,permission是具體的permission對(duì)象。 也可以通過(guò)用戶所在的組添加相應(yīng)的權(quán)限: group.permissions.set([permission_list]) group.permissions.add(permission, permission, …) group.permissions.remove(permission, permission, …) group.permissions.clear()

只要這個(gè)用戶加入該組也擁有組權(quán)限。通過(guò)User對(duì)象的get_all_permissions(obj=None)方法可以獲得該用戶的所有權(quán)限列表(字符列表),也可以通過(guò)get_group_permissions(obj=None)獲得對(duì)應(yīng)的組權(quán)限列表。

我們更經(jīng)常要做的是在view中執(zhí)行操作之前驗(yàn)證用戶是否擁有指定權(quán)限,這里一般用到User對(duì)象的has_perm(perm, obj=None)方法或者h(yuǎn)as_perms(perm_list, obj=None)判斷。

has_perm(perm, obj=None)方法中perm是”."格式的權(quán)限字符串, 如果有這個(gè)權(quán)限,方法會(huì)返回True。同樣,`has_perms(perm_list, obj=None)`方法中perm_list中是"."格式的權(quán)限字符串列表。

同login_required裝飾器,權(quán)限認(rèn)證也有對(duì)應(yīng)的permission_required裝飾器:

permission_required(perm, login_url=None, raise_exception=False)

如果raise_exception=True, 權(quán)限沒(méi)有認(rèn)證通過(guò)則拋出PermissionDenied異常,返回默認(rèn)的403頁(yè)面。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • python使用sorted函數(shù)對(duì)列表進(jìn)行排序的方法

    python使用sorted函數(shù)對(duì)列表進(jìn)行排序的方法

    這篇文章主要介紹了python使用sorted函數(shù)對(duì)列表進(jìn)行排序的方法,涉及Python使用sorted函數(shù)的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • Python如何對(duì)齊字符串

    Python如何對(duì)齊字符串

    這篇文章主要介紹了Python如何對(duì)齊字符串,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Python中動(dòng)態(tài)創(chuàng)建類實(shí)例的方法

    Python中動(dòng)態(tài)創(chuàng)建類實(shí)例的方法

    在Java中我們可以通過(guò)反射來(lái)根據(jù)類名創(chuàng)建類實(shí)例,那么在Python我們?cè)趺磳?shí)現(xiàn)類似功能呢?其實(shí)在Python有一個(gè)builtin函數(shù)import,我們可以使用這個(gè)函數(shù)來(lái)在運(yùn)行時(shí)動(dòng)態(tài)加載一些模塊
    2017-03-03
  • Python使用Paramiko庫(kù)實(shí)現(xiàn)SSH管理詳解

    Python使用Paramiko庫(kù)實(shí)現(xiàn)SSH管理詳解

    paramiko 是一個(gè)用于在Python中實(shí)現(xiàn)SSHv2協(xié)議的庫(kù),它支持對(duì)遠(yuǎn)程服務(wù)器進(jìn)行加密的通信,本文主要介紹了如何使用Paramiko庫(kù)實(shí)現(xiàn)SSH管理,感興趣的小伙伴可以學(xué)習(xí)一下
    2023-11-11
  • Appium Python自動(dòng)化測(cè)試之環(huán)境搭建的步驟

    Appium Python自動(dòng)化測(cè)試之環(huán)境搭建的步驟

    這篇文章主要介紹了Appium Python自動(dòng)化測(cè)試之環(huán)境搭建的步驟,以32位的Windows 7操作系統(tǒng)為例介紹Appium+Python的環(huán)境搭建步驟,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Python爬蟲(chóng)+Tkinter制作一個(gè)翻譯軟件的示例

    Python爬蟲(chóng)+Tkinter制作一個(gè)翻譯軟件的示例

    這篇文章主要介紹了Python爬蟲(chóng)+Tkinter制作一個(gè)翻譯軟件的示例,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-02-02
  • python調(diào)用百度語(yǔ)音REST API

    python調(diào)用百度語(yǔ)音REST API

    這篇文章主要為大家詳細(xì)介紹了python調(diào)用百度語(yǔ)音REST API,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • pytorch中使用cuda擴(kuò)展的實(shí)現(xiàn)示例

    pytorch中使用cuda擴(kuò)展的實(shí)現(xiàn)示例

    這篇文章主要介紹了pytorch中使用cuda擴(kuò)展的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Python并發(fā)編程線程消息通信機(jī)制詳解

    Python并發(fā)編程線程消息通信機(jī)制詳解

    這篇文章主要為大家介紹了Python并發(fā)編程之線程消息通信機(jī)制的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • 解決Scrapy安裝錯(cuò)誤:Microsoft Visual C++ 14.0 is required...

    解決Scrapy安裝錯(cuò)誤:Microsoft Visual C++ 14.0 is required...

    下面小編就為大家?guī)?lái)一篇解決Scrapy安裝錯(cuò)誤:Microsoft Visual C++ 14.0 is required...的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10

最新評(píng)論