先決條件: | 完成所有以前的教學(xué)課題,最多包括 Django教程第7部分:會話框架。 |
---|---|
目的: | 了解如何設(shè)置和使用用戶身份驗證和權(quán)限。 |
Django提供了一個認(rèn)證和授權(quán)("權(quán)限")系統(tǒng),該系統(tǒng)構(gòu)建在上一個教程中討論的會話框架之上,允許您驗證用戶憑據(jù) 并定義每個用戶允許執(zhí)行的操作。 該框架包括 Users
和 Groups
(一次向多個用戶應(yīng)用權(quán)限的通用方法)的內(nèi)置模型,用于指定用戶 可以執(zhí)行用于登錄用戶的任務(wù),表單和視圖,以及用于限制內(nèi)容的查看工具。
注意:根據(jù)Django,認(rèn)證系統(tǒng)旨在非常通用,因此不提供其他Web認(rèn)證系統(tǒng)中提供的一些功能。 一些常見問題的解決方案可用作第三方包。 例如,限制登錄嘗試和針對第三方的身份驗證(例如OAuth)。
在本教程中,我們將向您介紹如何在 LocalLibrary 中啟用用戶身份驗證, a>網(wǎng)站,創(chuàng)建您自己的登錄和注銷頁面,為您的模型添加權(quán)限,以及控制對頁面的訪問。 我們將使用身份驗證/權(quán)限來顯示為用戶和圖書館員借用的圖書列表。
認(rèn)證系統(tǒng)非常靈活,您可以從頭開始構(gòu)建您的URL,表單,視圖和模板,只需調(diào)用提供的API登錄用戶即可。 但是,在本文中,我們將使用Django的"stock"認(rèn)證視圖和表單登錄和注銷頁面。 我們?nèi)匀恍枰獎?chuàng)建一些模板,但這很容易。
我們還將向您展示如何創(chuàng)建權(quán)限,并檢查視圖和模板中的登錄狀態(tài)和權(quán)限。
當(dāng)我們創(chuàng)建骨架網(wǎng)站(在教程2中)時,會自動啟用身份驗證,因此您無需在此時再執(zhí)行任何操作。
注意:當(dāng)我們使用 django-admin startproject
命令創(chuàng)建應(yīng)用程序時,所有必要的配置都已完成。 當(dāng)我們第一次調(diào)用 python manage.py migrate
時,創(chuàng)建了用戶和模型權(quán)限的數(shù)據(jù)庫表。
配置在項目文件( locallibrary / locallibrary / settings.py )的 INSTALLED_APPS
和 MIDDLEWARE
部分中設(shè)置,如下所示:
INSTALLED_APPS = [ ... ? ? 'django.contrib.auth', #Core authentication framework and its default models. ? ? 'django.contrib.contenttypes', #Django content type system (allows permissions to be associated with models). .... MIDDLEWARE = [ ... ? ? 'django.contrib.sessions.middleware.SessionMiddleware', #Manages sessions across requests ... ? ? 'django.contrib.auth.middleware.AuthenticationMiddleware', #Associates users with requests using sessions. ....
當(dāng)我們在教程4中查看 Django管理網(wǎng)站時,您已經(jīng)創(chuàng)建了第一個用戶(這是一個超級用戶,使用命令 python manage創(chuàng)建)。
py createsuperuser)。 我們的超級用戶已經(jīng)通過身份驗證并擁有所有權(quán)限,因此我們需要創(chuàng)建一個測試用戶來代表一個正常的網(wǎng)站用戶。 我們將使用管理網(wǎng)站創(chuàng)建我們的 locallibrary 組和網(wǎng)站登錄,因為它是最快的方式之一。
注意:您也可以以編程方式創(chuàng)建用戶,如下所示。 你必須這樣做,例如,如果開發(fā)一個接口,允許用戶創(chuàng)建自己的登錄(你不應(yīng)該給用戶訪問管理站點)。
from django.contrib.auth.models import User # Create user and save to the database user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword') # Update fields and then save again user.first_name = 'John' user.last_name = 'Citizen' user.save()
下面我們先創(chuàng)建一個組,然后創(chuàng)建一個用戶。 即使我們沒有任何權(quán)限為我們的庫成員添加,如果我們需要以后,它會更容易一次添加到組,而不是單獨給每個成員。
啟動開發(fā)服務(wù)器,并導(dǎo)航到本地網(wǎng)絡(luò)瀏覽器中的管理網(wǎng)站( http://127.0.0.1:8000/ admin / )。 使用您的超級用戶帳戶的憑據(jù)登錄到網(wǎng)站。 管理網(wǎng)站的頂層顯示所有模型,按"django應(yīng)用程序"排序。 在驗證和授權(quán)部分中,您可以點擊用戶或網(wǎng)上論壇鏈接查看其現(xiàn)有記錄。
; width:661px;">
首先讓我們?yōu)閹斐蓡T創(chuàng)建一個新的組。
現(xiàn)在讓我們創(chuàng)建一個用戶:
而已!。 現(xiàn)在你有一個"正常的庫成員"帳戶,你將能夠用于測試(一旦我們實現(xiàn)了頁面,使他們能夠登錄)。
注意:您應(yīng)該嘗試創(chuàng)建其他庫成員用戶。 另外,為圖書館員創(chuàng)建一個組,并向其添加一個用戶!
Django提供了幾乎所有你需要創(chuàng)建的認(rèn)證頁面來處理登錄,注銷和密碼管理"開箱即用"。 這包括一個url映射器,視圖和表單,但它不包括模板 - 我們必須創(chuàng)建自己的!
在本節(jié)中,我們將介紹如何將默認(rèn)系統(tǒng)集成到LocalLibrary網(wǎng)站并創(chuàng)建模板。 我們將它們放在主項目URL中。
注意:您不必使用任何此類代碼,但很可能是您想要的,因為它使事情變得更容易。 如果您更改用戶模型(高級主題!),您幾乎肯定需要更改表單處理代碼,但即使如此,您仍然可以使用股票視圖功能。
請注意:在這種情況下,我們可以合理地將驗證頁(包括網(wǎng)址和模板)放入我們的目錄應(yīng)用程序中。 但是,如果我們有多個應(yīng)用程序,最好分離出這種共享登錄行為,并使其可用于整個網(wǎng)站,這是我們在這里顯示的!
將以下內(nèi)容添加到項目urls.py文件( locallibrary / locallibrary / urls.py )文件的底部:
#Add Django site authentication urls (for login, logout, password management) urlpatterns += [ url('^accounts/', include('django.contrib.auth.urls')), ]
導(dǎo)航到 http://127.0.0.1:8000/accounts/ 網(wǎng)址(請注意尾部正斜杠 !)和Django將顯示一個錯誤,它找不到這個URL,并列出了所有的URL。 從中可以看到可以工作的網(wǎng)址,例如:
^accounts/ ^login/$ [name='login'] ^accounts/ ^logout/$ [name='logout'] ^accounts/ ^password_change/$ [name='password_change'] ^accounts/ ^password_change/done/$ [name='password_change_done'] ^accounts/ ^password_reset/$ [name='password_reset'] ^accounts/ ^password_reset/done/$ [name='password_reset_done'] ^accounts/ ^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm'] ^accounts/ ^reset/done/$ [name='password_reset_complete']
現(xiàn)在,嘗試導(dǎo)航到登錄網(wǎng)址( http://127.0.0.1:8000/accounts/login/ / a>)。 此操作會再次失敗,但出現(xiàn)錯誤,告知您我們在模板搜索路徑中缺少必需的模板( registration / login.html )。 您會在頂部的黃色部分看到以下行:
Exception Type: TemplateDoesNotExist Exception Value: registration/login.html
下一步是在搜索路徑上創(chuàng)建注冊目錄,然后添加 login.html 文件。
我們剛才添加的url(和隱式視圖)希望在模板搜索路徑中的某個位置的 / registration / 目錄中找到它們相關(guān)的模板。 對于此網(wǎng)站,我們會將模板放置在 templates / registration / 目錄中(即將模板放置在最上層目錄 和 locallibrary 文件夾) - 請立即創(chuàng)建模板和注冊目錄。
要使這些目錄對模板加載器可見(即將此目錄放在模板搜索路徑中),請打開項目設(shè)置( /locallibrary/locallibrary/settings.py ),然后更新 TEMPLATES
部分的\'DIRS\'
行,如圖所示。
TEMPLATES = [ { ... 'DIRS': ['./templates',], 'APP_DIRS': True, ...
重要:本文中提供的身份驗證模板是Django演示登錄模板的非常基本/稍微修改的版本。 您可能需要自定義它們?yōu)槟约菏褂茫?/span>
創(chuàng)建一個名為/ locallibrary / templates / registration / login.html 的新HTML文件。 給它以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} {% if form.errors %} <p>Your username and password didn't match. Please try again.</p> {% endif %} {% if next %} ? ? {% if user.is_authenticated %} ? ? <p>Your account doesn't have access to this page. To proceed, ? ? please login with an account that has access.</p> ? ? {% else %} ? ? <p>Please login to see this page.</p> ? ? {% endif %} {% endif %} <form method="post" action="{% url 'login' %}"> {% csrf_token %} <div> ? <td>{{ form.username.label_tag }}</td> ? <td>{{ form.username }}</td> </div> <div> ? <td>{{ form.password.label_tag }}</td> ? <td>{{ form.password }}</td> </div> <div> ? <input type="submit" value="login" /> ? <input type="hidden" name="next" value="" /> </div> </form> {# Assumes you setup the password_reset view in your URLconf #} <p><a href="{% url 'password_reset' %}">Lost password?</a></p> {% endblock %}
此模板與我們之前看到的模板有一些相似之處 - 它擴展了我們的基本模板,并覆蓋了 content
塊。 其余的代碼是相當(dāng)標(biāo)準(zhǔn)的表單處理代碼,我們將在后面的教程中討論。 您現(xiàn)在需要知道的是,這將顯示一個窗體,您可以在其中輸入您的用戶名和密碼,如果您輸入無效的值,將提示您在頁面刷新時輸入正確的值。
返回登錄頁面( http://127.0.0.1:8000/accounts/login/ >),一旦您保存了模板,您應(yīng)該看到這樣:
; width:441px;">
如果您嘗試登錄將成功,您將被重定向到另一個頁面(默認(rèn)情況下,這將是 http ://127.0.0.1:8000 / accounts / profile / )。 這里的問題是,默認(rèn)情況下Django期望在登錄后,你會想要到一個配置文件頁面,這可能是或不是這種情況。 由于您尚未定義此網(wǎng)頁,因此您會收到另一個錯誤訊息!
打開項目設(shè)置( /locallibrary/locallibrary/settings.py ),然后將下面的文字添加到底部。 現(xiàn)在,當(dāng)您登錄時,您應(yīng)該被重定向到網(wǎng)站主頁默認(rèn)情況下。
# Redirect to home URL after login (Default redirects to /accounts/profile/) LOGIN_REDIRECT_URL = '/'
如果您導(dǎo)航到注銷網(wǎng)址( http://127.0.0.1:8000/accounts/logout/ a>),那么您會看到一些奇怪的行為 - 您的用戶將被確實注銷,但您會轉(zhuǎn)到管理注銷頁面。 這不是你想要的,如果只是因為該頁面上的登錄鏈接會轉(zhuǎn)到管理員登錄屏幕(只有擁有 is_staff
權(quán)限的用戶才能使用)。
創(chuàng)建并打開/ locallibrary / templates / registration / logged_out.html 。 在下面的文本中復(fù)制:
{% extends "base_generic.html" %} {% block content %} <p>Logged out!</p> <a href="{% url 'login'%}">Click here to login again.</a> {% endblock %}
這個模板很簡單。 它只是顯示一條消息,通知您已注銷,并提供一個鏈接,您可以按返回登錄屏幕。 如果再次訪問注銷URL,您應(yīng)該會看到此頁面:
; width:385px;">
默認(rèn)密碼重置系統(tǒng)使用電子郵件向用戶發(fā)送重置鏈接。 您需要創(chuàng)建表單以獲取用戶的電子郵件地址,發(fā)送電子郵件,允許他們輸入新密碼,并在整個過程完成時注意。
以下模板可用作起點。
這是用于獲取用戶的電子郵件地址(用于發(fā)送密碼重置電子郵件)的表單。 創(chuàng)建 /locallibrary/templates/registration/password_reset_form.html ,并提供以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} <form action="" method="post">{% csrf_token %} {% if form.email.errors %} {{ form.email.errors }} {% endif %} <p>{{ form.email }}</p> <input type="submit" class="btn btn-default btn-lg" value="Reset password" /> </form> {% endblock %}
此表單在您的電子郵件地址收集后顯示。 創(chuàng)建 /locallibrary/templates/registration/password_reset_done.html ,并提供以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} <p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p> {% endblock %}
此模板提供了我們將發(fā)送給用戶的HTML電子郵件的文本,其中包含重置鏈接。 創(chuàng)建 /locallibrary/templates/registration/password_reset_email.html ,并提供以下內(nèi)容:
Someone asked for password reset for email {{ email }}. Follow the link below: {{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
此頁面是您在單擊密碼重置電子郵件中的鏈接后輸入新密碼的位置。 創(chuàng)建 /locallibrary/templates/registration/password_reset_confirm.html ,并提供以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} {% if validlink %} <p>Please enter (and confirm) your new password.</p> <form action="" method="post"> <div style="display:none"> <input type="hidden" value="{{ csrf_token }}" name="csrfmiddlewaretoken"> </div> <table> <tr> <td>{{ form.new_password1.errors }} <label for="id_new_password1">New password:</label></td> <td>{{ form.new_password1 }}</td> </tr> <tr> <td>{{ form.new_password2.errors }} <label for="id_new_password2">Confirm password:</label></td> <td>{{ form.new_password2 }}</td> </tr> <tr> <td></td> <td><input type="submit" value="Change my password" /></td> </tr> </table> </form> {% else %} <h1>Password reset failed</h1> <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p> {% endif %} {% endblock %}
這是最后一個密碼重置模板,顯示該模板以在密碼重置成功時通知您。 創(chuàng)建 /locallibrary/templates/registration/password_reset_complete.html ,并提供以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} <h1>The password has been changed!</h1> <p><a href="{% url 'login' %}">log in again?</a></p> {% endblock %}
現(xiàn)在您已添加了網(wǎng)址配置并創(chuàng)建了所有這些模板,驗證頁面現(xiàn)在應(yīng)該可以正常工作了!
您可以嘗試使用以下網(wǎng)址登錄并注銷超級用戶帳戶,以測試新的身份驗證頁:
您可以從登錄頁面的鏈接中測試密碼重置功能。 請注意,Django只會向已存儲在其數(shù)據(jù)庫中的地址(用戶)發(fā)送重置電子郵件!
注意:密碼重置系統(tǒng)要求您的網(wǎng)站支持電子郵件,這超出了本文的范圍,因此此部分無法使用。 要允許測試,請將以下行放在settings.py文件的末尾。 這會記錄發(fā)送到控制臺的任何電子郵件(因此您可以從控制臺復(fù)制密碼重置鏈接)。
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
有關(guān)詳細(xì)信息,請參見發(fā)送電子郵件(Django docs)。
本節(jié)討論我們可以做什么來根據(jù)用戶是否登錄來選擇性地控制用戶看到的內(nèi)容。
您可以使用 {{user}}
模板變量獲取模板中當(dāng)前登錄用戶的信息(當(dāng)我們在我們的骨架中設(shè)置項目時,默認(rèn)將其添加到模板上下文中 )。
通常,您將首先針對 {{user.is_authenticated}}
模板變量進(jìn)行測試,以確定用戶是否有資格查看特定內(nèi)容。 為了演示這一點,接下來我們將更新側(cè)邊欄,如果用戶已注銷則顯示"登錄"鏈接,如果他們已登錄,則顯示"注銷"鏈接。
打開基本模板( /locallibrary/catalog/templates/base_generic.html ),然后將以下文本復(fù)制到 sidebar
塊中緊挨 endblock
>模板標(biāo)簽。
<ul class="sidebar-nav"> ... {% if user.is_authenticated %} <li>User: {{ user.get_username }}</li> <li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li> {% else %} <li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li> {% endif %} </ul>
如您所見,我們使用 if
- else
- endif
模板標(biāo)簽有條件地顯示文本,基于 {{user.is_authenticated
}} 為true。 如果用戶通過身份驗證,我們知道我們有一個有效的用戶,因此我們調(diào)用 {{user.get_username}} 來顯示他們的名字。
我們使用 url
模板標(biāo)記和相應(yīng)網(wǎng)址配置的名稱創(chuàng)建登錄和注銷鏈接網(wǎng)址。 還要注意我們?nèi)绾卧赨RL的末尾附加?next = {{request.path}}
。 此操作是添加包含當(dāng)前頁面的地址(URL)的下一步 ,到鏈接的URL的結(jié)尾。 在用戶成功登錄/注銷后,視圖將使用此" next
"值將用戶重定向到他們首次單擊登錄/注銷鏈接的頁面。
注意:嘗試一下! 如果您在主頁上,并單擊側(cè)邊欄中的登錄/注銷,則操作完成后,您應(yīng)該返回到同一頁面。
如果使用基于函數(shù)的視圖,限制對函數(shù)的訪問的最簡單的方法是將 login_required
裝飾器應(yīng)用于視圖函數(shù),如下所示。 如果用戶登錄,那么您的視圖代碼將正常執(zhí)行。 如果用戶未登錄,則將重定向到項目設(shè)置( settings.LOGIN_URL
)中定義的登錄URL,將當(dāng)前絕對路徑作為 next
URL參數(shù)傳遞 。 如果用戶成功登錄,則他們將返回此頁面,但這次被驗證。
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
注意:您可以通過在 request.user.is_authenticated
上測試手動完成相同類型的事情,但裝飾器更方便!
同樣,在基于類的視圖中限制對已登錄用戶的訪問的最簡單方法是從 LoginRequiredMixin
派生。 您需要在超類列表中,在主視圖類之前首先聲明此混合。
from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): ...
這具有與 login_required
裝飾器完全相同的重定向行為。 您還可以指定用戶重定向的替代位置(如果未通過身份驗證( login_url
)和URL參數(shù)名稱而不是" next
"以插入當(dāng)前絕對 路徑( redirect_field_name
)。
class MyView(LoginRequiredMixin, View): login_url = '/login/' redirect_field_name = 'redirect_to'
有關(guān)其他詳細(xì)信息,請查看 > Django docs here 。
現(xiàn)在我們知道如何將頁面限制為特定用戶,讓我們創(chuàng)建當(dāng)前用戶借用的書籍的視圖。
不幸的是,我們還沒有辦法讓用戶借書! 因此,在我們創(chuàng)建書籍列表之前,我們首先擴展 BookInstance
模型,以支持借用的概念,并使用Django Admin應(yīng)用程序?qū)⒁恍杞o我們的測試用戶。
首先,我們必須讓用戶有一個 BookInstance
(我們已經(jīng)有一個狀態(tài)
和 due_back
日期 ,但是我們還沒有在這個模型和用戶之間有任何關(guān)聯(lián),我們將使用 ForeignKey
(一對多)字段創(chuàng)建一個,我們還需要一個簡單的機制來測試 一本借來的書已經(jīng)逾期了。
打開 catalog / models.py ,然后從 django.contrib.auth.models
中導(dǎo)入 User
在文件的頂部,因此 User
可用于使用它的后續(xù)代碼):
from django.contrib.auth.models import User
接下來將 borrower
字段添加到 BookInstance
模型中:
borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
當(dāng)我們在這里時,我們添加一個屬性,我們可以從我們的模板調(diào)用,以告訴特定的書實例是否過期。 雖然我們可以在模板本身計算,使用如下所示的屬性將更加高效。
from datetime import date @property def is_overdue(self): if date.today() > self.due_back: return True return False
現(xiàn)在我們更新了模型,我們需要對項目進(jìn)行新的遷移,然后應(yīng)用這些遷移:
python3 manage.py makemigrations python3 manage.py migrate
現(xiàn)在打開 catalog / admin.py ,并將 borrower
字段添加到 list_display
中的 BookInstanceAdmin
fieldsets
,如下所示。 這將使該字段在管理員部分中可見,以便我們可以在需要時將 User
分配給 BookInstance
。
@admin.register(BookInstance) class BookInstanceAdmin(admin.ModelAdmin): ? ? list_display = ('book', 'status', 'borrower', 'due_back', 'id') ? ? list_filter = ('status', 'due_back') ? ?? ? ? fieldsets = ( ? ? ? ? (None, { ? ? ? ? ? ? 'fields': ('book','imprint', 'id') ? ? ? ? }), ? ? ? ? ('Availability', { ? ? ? ? ? ? 'fields': ('status', 'due_back','borrower',) ? ? ? ? }), ? ? )
現(xiàn)在,它可以借書給特定的用戶,去借出一些 BookInstance
記錄(設(shè)置他們的借用
字段給你的測試用戶,使 狀態(tài)"貸款"并在未來和過去設(shè)置到期日。
注意:我們不會拼寫此過程,因為您已經(jīng)知道如何使用管理網(wǎng)站!
現(xiàn)在,我們將添加一個視圖,以獲取已借給當(dāng)前用戶的所有圖書的列表。 我們將使用我們熟悉的相同的通用基于類的列表視圖,但是這次我們還將從 LoginRequiredMixin
導(dǎo)入和派生,以便只有已登錄的用戶可以調(diào)用此視圖。 我們還將選擇聲明一個 template_name
,而不是使用默認(rèn)值,因為我們最終可能會有一些不同的BookInstance記錄列表,以及不同的視圖和模板。
將以下內(nèi)容添加到catalog / views.py中:
from django.contrib.auth.mixins import LoginRequiredMixin class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView): """ Generic class-based view listing books on loan to current user. """ model = BookInstance template_name ='catalog/bookinstance_list_borrowed_user.html' paginate_by = 10 def get_queryset(self): return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')
為了將我們的查詢限制為當(dāng)前用戶的BookInstance對象,我們?nèi)缟纤局匦聦崿F(xiàn) get_queryset()
。 請注意,"o"是"借出"的存儲代碼,我們通過 due_back
日期排序,以便先顯示最早的項目。
現(xiàn)在打開 /catalog/urls.py ,并添加一個指向上述視圖的 url()
(您只需將下面的文本復(fù)制到文件末尾即可)。
urlpatterns += [ url(r'^mybooks/$', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'), ]
現(xiàn)在我們需要為這個頁面做的是添加一個模板。 首先,創(chuàng)建模板文件 /catalog/templates/catalog/bookinstance_list_borrowed_user.html ,并提供以下內(nèi)容:
{% extends "base_generic.html" %} {% block content %} <h1>Borrowed books</h1> {% if bookinstance_list %} <ul> {% for bookinst in bookinstance_list %} <li class="{% if bookinst.is_overdue %}text-danger{% endif %}"> <a href="{% url 'book-detail' bookinst.book.pk %}">{{bookinst.book.title}}</a> ({{ bookinst.due_back }}) </li> {% endfor %} </ul> {% else %} <p>There are no books borrowed.</p> {% endif %} {% endblock %}
此模板非常類似于之前為 Book
和 Author
對象創(chuàng)建的模板。 這里唯一的"新"是我們檢查在模型(bookinst.is_overdue
)中添加的方法,并使用它來改變過期項目的顏色。
當(dāng)開發(fā)服務(wù)器運行時,您現(xiàn)在應(yīng)該可以在瀏覽器中查看登錄用戶的列表, > http://127.0.0.1:8000/catalog/mybooks/ 。 嘗試這與您的用戶登錄并注銷(在第二種情況下,您應(yīng)該被重定向到登錄頁面)。
最后一步是將這個新頁面的鏈接添加到側(cè)邊欄。 我們將把它放在我們顯示已登錄用戶的其他信息的同一部分。
打開基本模板( /locallibrary/catalog/templates/base_generic.html ),然后將粗線添加到側(cè)邊欄,如圖所示。
<ul class="sidebar-nav"> {% if user.is_authenticated %} <li>User: {{ user.get_username }}</li> <li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li> <li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li> {% else %} <li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li> {% endif %} </ul>
當(dāng)任何用戶登錄時,他們會在側(cè)邊欄中看到我的借閱鏈接,并且顯示的書籍列表如下(第一本書沒有到期日,這是我們希望的錯誤 在后面的教程中修復(fù)!)。
; width:530px;">
權(quán)限與模型相關(guān)聯(lián),并定義具有權(quán)限的用戶可以在模型實例上執(zhí)行的操作。 默認(rèn)情況下,Django會自動為所有模型提供添加,更改和權(quán)限,允許具有相關(guān)權(quán)限的用戶通過 管理網(wǎng)站。 您可以為模型定義自己的權(quán)限,并將其授予特定用戶。 您還可以更改與同一模型的不同實例關(guān)聯(lián)的權(quán)限。
測試視圖和模板中的權(quán)限非常類似,用于測試身份驗證狀態(tài)(實際上,測試權(quán)限也會測試身份驗證)。
使用 permissions
字段在模型" class Meta
"中定義權(quán)限。 您可以在元組中指定任意數(shù)量的權(quán)限,每個權(quán)限本身在包含權(quán)限名稱和權(quán)限顯示值的嵌套元組中定義。 例如,我們可以定義一個權(quán)限,以允許用戶標(biāo)記圖書已返回,如圖所示:
class BookInstance(models.Model): ... ? class Meta: ? ... permissions = (("can_mark_returned", "Set book as returned"),)
然后,我們可以將權(quán)限分配給管理網(wǎng)站中的"圖書管理員"組。
打開 catalog / models.py ,然后添加如上所示的權(quán)限。 您需要重新運行遷移(調(diào)用 python3 manage.py makemigrations
和 python3 manage.py migrate
)以適當(dāng)?shù)馗聰?shù)據(jù)庫。
當(dāng)前用戶的權(quán)限存儲在名為 {{perms}}
的模板變量中。 您可以使用相關(guān)聯(lián)的Django"應(yīng)用"中的特定變量名稱來檢查當(dāng)前用戶是否具有特定權(quán)限。 如果用戶具有此權(quán)限,則 {{perms.catalog.can_mark_returned}}
將為 True
,否則為 False
。 我們通常使用模板 {%if%}
來測試權(quán)限,如下所示:
{% if perms.catalog.can_mark_returned
%}
<!-- We can mark a BookInstance as returned. -->
? <!-- Perhaps add code to link to a "book return" view here. -->
{% endif %}
權(quán)限可以在函數(shù)視圖中使用 permission_required
裝飾器或在基于類的視圖中使用 PermissionRequiredMixin
來測試。 模式和行為與登錄身份驗證相同,但當(dāng)然您可能需要添加多個權(quán)限。
函數(shù)視圖裝飾器:
from django.contrib.auth.decorators import permission_required @permission_required('catalog.can_mark_returned
') @permission_required('catalog.can_edit
') def my_view(request): ...
基于類的視圖的權(quán)限所需的混合。
from django.contrib.auth.mixins import PermissionRequiredMixin class MyView(PermissionRequiredMixin, View): permission_required = 'catalog.can_mark_returned
' # Or multiple of permissions: permission_required = ('catalog.can_mark_returned
', 'catalog.can_edit')
我們不會在此更新 LocalLibrary ; 也許在下一個教程!
在本文前面,我們向您展示了如何為當(dāng)前用戶創(chuàng)建一個頁面,列出他們借用的書籍。 現(xiàn)在的挑戰(zhàn)是創(chuàng)建一個類似的頁面,該頁面僅對圖書館員可見,顯示已借用的所有圖書,其中包括每位借款人的姓名。
您應(yīng)該能夠遵循與其他視圖相同的模式。 主要區(qū)別是,您需要將視圖限制為只有圖書館員。 您可以根據(jù)用戶是否是工作人員(函數(shù)裝飾: staff_member_required
,模板變量: user.is_staff
)來執(zhí)行此操作,但建議您改用 > can_mark_returned
權(quán)限和 PermissionRequiredMixin
,如上一節(jié)所述。
重要:記住不要使用超級用戶進(jìn)行基于權(quán)限的測試(即使尚未定義權(quán)限,權(quán)限檢查也始終對超級用戶返回true)。 而是創(chuàng)建庫管理器用戶,并添加所需的功能。
完成后,您的網(wǎng)頁應(yīng)該如下面的屏幕截圖所示。
; width:500px;">
優(yōu)秀的工作 - 你現(xiàn)在創(chuàng)建了一個網(wǎng)站,圖書館成員可以登錄并查看自己的內(nèi)容,圖書館員(具有正確的權(quán)限)可以使用查看所有借出的圖書和他們的借款人。 目前我們?nèi)匀恢皇遣榭磧?nèi)容,但是當(dāng)您想要開始修改和添加數(shù)據(jù)時,使用相同的原理和技術(shù)。
在下一篇文章中,我們將討論如何使用Django表單收集用戶輸入,然后開始修改一些存儲的數(shù)據(jù)。
更多建議: