iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 27
0

我們今天要來設定一個使者登錄註冊和身分驗證的系統,讓使用者可以註冊帳號,並能夠登入和登出

user應用程式

首先我們要先用startapp命令來建立名為users應用程式,如下
python manage.py startapp users

然後我們可以看現在的learning_log目錄多了users的應用程式,也可以看users目錄裡面的結構跟learning_logs相同,如下

把users加到setting.py中

將users應用程式引入整個專案中,如下

INSTALLED_APPS = (
--省略--
    'learning_logs',
    'users', # 新增區塊
)

放入users應用程式的URL

我們加了一行程式碼來引入users應用程式中的urls.py檔,這行程式碼與任何以users為開頭的URL都比對符合,如下

from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls')), # 新增區塊
    path('', include('learning_logs.urls')),
]

登入

登入的URL模式

我們現在要來做login的頁面,我們會在users資料夾裡面新增一個urls.py檔,如下

from django.conf.urls import url
from django.urls import path
from django.contrib.auth.views import LoginView
from . import views

app_name='users'

urlpatterns = [    
    path('login/', LoginView.as_view(template_name='users/login.html'), name="login"),
]

上面程式碼我們先在第三行匯入LoginView視圖,第九行是登入頁面的URL模式與URL http://localhost:8000/users/login 相配符合

登入模板

使用者請求登入頁面時,Django會使用預設login視圖來處理,但我們還是需要為這個網頁提供模板,首先要在users資料夾裡建立一個templates資料夾,在templates資料夾中再建立一個users資料夾,裡面新增一個login.html,如下

{% extends "learning_logs/base.html" %}

{% block content %}

  {% if form.errors %}
    <p>Your username and password didn't match. Please try again.</p>
  {% endif %}
    
  <form method="post" action="{% url 'users:login' %}">
    {% csrf_token %}
    {{ form.as_p }}
    
    <button name="submit">log in</button> 
    <input type="hidden" name="next"
      value="{% url 'learning_logs:index' %}" />
  </form>
    
{% endblock content %}

上面程式碼第五行是如果表單errors屬性被設定,就會顯示一條錯誤訊息,回報輸入的使用者名稱-密碼對與資料庫中儲存的都不相符,第十四行這裡放入一個隱藏的表單元素next,其中的引數會告知Django在使用者成功登入後會重新導向主頁

連結到登入頁面

在base.html中新增連到login頁面的連結,如下

<p>
--省略--
  {% if user.is_authenticated %}
    Hello, {{ user.username }}.
  {% else %}
    <a href="{% url 'users:login' %}">log in</a> 
  {% endif %}
</p>

{% block content %}{% endblock %}

上面程式碼第三和第四行是如果使用者已登入就不會顯示連結

登入頁面如下

未登入使用者會先看到log in 連結

點進去後可以輸入使用者帳號和密碼

登出

我們現在要來做的是登出,我們不用建立登出頁面,至要讓使用者按一個連結就可以登出並返回主頁

登出的URL模式

--省略--
urlpatterns = [
--省略--
    path('logout/', views.logout_view, name='logout'),
]

logout_view()視圖模式

匯入Django的logout()函式並呼叫它,再重新導向主頁,首先我們要開啟users資料夾中的views.py檔,如下

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout # 匯入logout函式
from django.urls import reverse

def logout_view(request): # 呼叫logout函式,它會把request當作引數,然後重新導向主頁
    logout(request)
    return HttpResponseRedirect(reverse('learning_logs:index'))

連結到logout視圖

在base.html中新增連到logout的連結,如下

<p>
  --省略--
  {% if user.is_authenticated %}
    Hello, {{ user.username }}.
    <a href="{% url 'users:logout' %}">log out</a>
  {% else %}
  --省略--
  {% endif %}
</p>

{% block content %}{% endblock %}

將第五行的logout連結放在if區塊內是因為只有在使用者登入時才能看到logout連結

登出連結如下

登入註冊頁面

這裡要建立讓使用者可以登錄註冊的頁面,我們會使用Django預設提供的UserCreationForm表單

登入註冊的URL模式

--省略--
urlpatterns = [
--省略--
    path('register/', views.register, name='register'),
]

register()視圖函式

在登入註冊頁面第一次被請求時,register視圖函是需要顯是一個空的物註冊表單,並在使用者填好資料提交表單時對它進行處理,如果登入註冊成功,這個函式還需要讓使用者登入系統,現在我們要開啟views.py檔來新增一些程式碼,如下

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.urls import reverse
from django.contrib.auth.forms import UserCreationForm
--省略--
def register(request):
    """Register a new user."""
    if request.method != 'POST':  
        form = UserCreationForm()
    else:
        form = UserCreationForm(data=request.POST)
        
        if form.is_valid():
            new_user = form.save()
            authenticated_user = authenticate(username=new_user.username,
                password=request.POST['password1'])
            login(request, authenticated_user)
            return HttpResponseRedirect(reverse('learning_logs:index'))

    context = {'form': form}
    return render(request, 'users/register.html', context)

登入註冊模板

新增一個register.html檔放在和login.html同一個資料夾,如下

{% extends "learning_logs/base.html" %}

{% block content %}

  <form method="post" action="{% url 'users:register' %}">
    {% csrf_token %}
    {{ form.as_p }}
        
    <button name="submit">register</button>
    <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
  </form>
    
{% endblock content %}

登錄註冊頁面的連結

在base.html中新增連到登入頁面的連結,如下

<p>
--省略--
  {% else %}
    <a href="{% url 'users:register' %}">register</a> -
--省略--
  {% endif %}
</p>

{% block content %}{% endblock %}

登入註冊連結如下

會看到主頁多了register連結

點進來後會看到預設的表單

附上排版較精美的
HackMD網址:https://hackmd.io/k4M00PB4TDKybC0IAJtCQw?both

今天結束,各位明天見


資料來源:<<python程式設計的樂趣>>-Eric Matthes著/H&C譯
資料來源:https://stackoverflow.com/questions/51906428/django-cannot-import-login-from-django-contrib-auth-views/51906537
資料來源:https://github.com/ehmatthes/pcc/tree/master/chapter_19#p-439-including-the-urls-from-users


上一篇
DAY 26 Django允許使用者輸入資料
下一篇
DAY 28 Django允許使用者擁有自己的資料
系列文
初學者Python的應用實作30

尚未有邦友留言

立即登入留言