django搭建一個資產管理系統2.登入系統
思路:先在本機建立好專案,再移植到伺服器上,本機環境儘量與Server端環境一樣,
python3.6 django2.2.0
開發軟體 pycharm
首先建立專案sams (Server assets management system)
django-admin startproject sams
cd sams
python manage.py startapp login
檢視目錄結構
然後設定語言和時區,在setting中修改LANGUAGE_CODE和TIME_ZONE,修改為
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'
然後啟用專案,成功後用瀏覽器訪問127.0.0.1:8000如下圖所示
python manage.py runserver
我們使用資料庫管理登入的賬戶密,所以我們登入到Server上
mysq -u root -p #然後按兩下回車登入mysql GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; // %:表示從任何主機連線到mysql伺服器,password自己任意設定 FLUSH PRIVILEGES; // 重新整理資料庫 CREATE DATABASE sams CHARACTER SET utf8; show databases; //當然你可以新建其他登入mysql的賬戶並設定許可權,此處只是為了省事兒
然後我們連線使用django連線資料庫
依賴pymysql
pip install pymysql
修改setting, 在前面加上 import pymysql
在之後在setting中找到之前DATABASES,將其註釋掉.然後指定自己server端的mysql資料庫
""" DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } """ pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 資料庫引擎 'NAME': 'sams', # 資料庫名,先前建立的 'USER': 'root', # 使用者名稱,可以自己建立使用者 'PASSWORD': 'password', # 密碼 'HOST': '10.244.220.220', # mysql服務所在的主機ip 'PORT': '3306', # mysql服務埠 } }
至此資料庫設定已完成
然後就是資料庫模型設定
此處我只把註冊當成一個限制登入的操作,所以很多東西都可以不新增,有需要的話再舉一反三進行新增相關欄位(我只需要賬戶,密碼,有需要可以再新增一些性別,建立日期,管理員/使用者等)
進入login/models.py
檔案
from django.db import models
# Create your models here.
class User(models.Model):
name=models.CharField(max_length=128,unique=True)
password=models.CharField(max_length=256)
class Meta:
ordering = ["name"]
db_table='user'
然後註冊app(login為一個app),每新增一個app都需要在settings裡面設定
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
]
app中的models建立好了後,並不會自動地在資料庫中生成相應的資料表,需要你手動建立。
進入Pycharm的terminal終端,執行下面的命令:
python manage.py makemigrations
返回結果:
D:\aworkstation\sams>python manage.py makemigrations
Migrations for 'login':
login\migrations\0001_initial.py
- Create model User
D:\aworkstation\sams>
Django自動為我們建立了login\migrations\0001_initial.py
檔案,儲存了我們的第一次資料遷移工作,也就是建立了User模型。
接著執行下面的命令:
python manage.py migrate
Django將在資料庫內建立真實的資料表。如果是第一次執行該命令,那麼一些內建的框架,比如auth、session等的資料表也將被一同建立,如下所示:
D:\aworkstation\sams>python manage.py migrate
System check identified some issues:
WARNINGS:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
HINT: MySQL's Strict Mode fixes many data integrity problems in MySQL, such as data truncation upon insertion, by escalating warnings in
to errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-sql-mode
Operations to perform:
Apply all migrations: admin, auth, contenttypes, login, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying login.0001_initial... OK
Applying sessions.0001_initial... OK
D:\aworkstation\sams>
在mysql上就可以看到新建的表了
MariaDB [(none)]> use sams;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [sams]> show tables;
+----------------------------+
| Tables_in_sams |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
| user |
+----------------------------+
11 rows in set (0.00 sec)
MariaDB [sams]>
但此時表的內容是空的
MariaDB [sams]> select * from user;
Empty set (0.00 sec)
我們進行到下一步,使用django自帶的admin後臺管理,在admin中註冊這個模型
進入login/admin.py
檔案,程式碼如下:
from django.contrib import admin
# Register your models here.
from . import models
admin.site.register(models.User)
Django的admin後臺擁有完整的較為安全的使用者認證和授權機制,防護等級還算可以。
要進入該後臺,需要建立超級管理員,該管理員和我們先前建立的User使用者不是一個概念,要注意區別對待。
同樣在Pycharm的終端中,執行下面的命令:
python manage.py createsuperuser
D:\aworkstation\sams>python manage.py createsuperuser
使用者名稱 (leave blank to use 'Administrator'): admin
電子郵件地址:
Password:
Password (again):
Superuser created successfully.
D:\aworkstation\sams>
然後執行Python manage.py runserver 就可以啟動我們的開發伺服器了,然後在瀏覽器中訪問http://127.0.0.1:8000/admin/
地址
就可以輸入賬戶密碼登入了 登入後的介面如圖所示
然後我們就可以新增一個使用者了
此時在mysql中就可以看到新建的賬戶了
MariaDB [sams]> select * from user;
+----+-------+----------+
| id | name | password |
+----+-------+----------+
| 1 | admin | password |
+----+-------+----------+
1 row in set (0.00 sec)
然後就是路由設計了
重要說明:由於本專案目的是打造一個針對管理系統、應用程式等需求下的可重用的登入/註冊app,而不是入口網站、免費部落格等無需登入即可訪問的網站,所以在url路由、跳轉策略和檔案結構的設計上都是儘量自成體系。具體訪問的策略如下:
- 未登入人員,不論是訪問index還是login和logout,全部跳轉到login介面
- 已登入人員,訪問login會自動跳轉到index頁面
- 已登入人員,不允許直接訪問register頁面,需先logout
- 登出後,自動跳轉到login介面
根據上面的策劃,開啟sams/url.py檔案,寫入下面的程式碼:
from django.contrib import admin
from django.urls import path
from login import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
path('login/', views.login),
path('register/', views.register),
path('logout/', views.logout),
]
此時會有報警的下劃線產生,這是因為我們還沒在login中配置views,我們下一步就是去編輯/login/views檔案
from django.shortcuts import render
from django.shortcuts import redirect
# Create your views here.
def index(request):
pass
return render(request, 'login/index.html')
def login(request):
pass
return render(request, 'login/login.html')
def register(request):
pass
return render(request, 'login/register.html')
def logout(request):
pass
return redirect("/login/")
此處只搭建了一個基礎框架,然後開始HTML介面
在專案根路徑的login目錄中建立一個templates目錄,再在templates目錄裡建立一個login目錄。這麼做有助於app複用,防止命名衝突,能更有效地組織大型工程.當然這一段是我抄的
在login/templates/login
目錄中建立三個檔案index.html
、login.html
以及register.html
,並寫入如下的程式碼:
index.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首頁</title> </head> <body> <h1>這僅僅是一個主頁模擬!請根據實際情況接入正確的主頁!</h1> </body> </html>
login.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登入</title> </head> <body> <h1>登入頁面</h1> </body> </html>
register.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>註冊</title> </head> <body> <h1>註冊頁面</h1> </body> </html>
現在我們的專案架構如圖所示
啟動伺服器,在瀏覽器訪問http://127.0.0.1:8000/index/
等頁面,如果能正常顯示,說明一切OK!
現在,我們整個專案的基本框架已經搭建起來了!
再之後就是修改登入介面了
修改login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登入</title>
</head>
<body>
<div style="margin: 15% 40%;">
<h1>歡迎登入!</h1>
<form action="/login/" method="post">
<p>
<label for="id_username">使用者名稱:</label>
<input type="text" id="id_username" name="username" placeholder="使用者名稱" autofocus required />
</p>
<p>
<label for="id_password">密碼:</label>
<input type="password" id="id_password" placeholder="密碼" name="password" required >
</p>
<input type="submit" value="確定">
</form>
</div>
</body>
</html>
再訪問就可以看到介面是這個樣子
這個介面很醜,所以我們得引入bootstrap4,前端真的是一言難盡啊,花樣太多了
修改login.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 上述meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<!-- Bootstrap CSS -->
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<title>登入</title>
</head>
<body>
<div class="container">
<div class="col">
<form class="form-login" action="/login/" method="post">
<h3 class="text-center">歡迎登入</h3>
<div class="form-group">
<label for="id_username">使用者名稱:</label>
<input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
</div>
<div class="form-group">
<label for="id_password">密碼:</label>
<input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required>
</div>
<div>
<a href="/register/" class="text-success "><ins>新使用者註冊</ins></a>
<button type="submit" class="btn btn-primary float-right">登入</button>
</div>
</form>
</div>
</div> <!-- /container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{# 以下三者的引用順序是固定的#}
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
此時介面就是這樣的
但若是內網環境(因為之前引入的js,jQuery這些都是直接引用的網上的,我們需要下載下來),載入很久之後會變成這樣
此時我們需要將引用的js,jQuery下載到本地,首先在login下新建static/login/css/,新建一個txt,重新命名為與之相同的名字,如bootstrap.min.js
然後在瀏覽器輸入https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css,全選複製,然後貼上到之前的那個檔案中.
然後再修改login.html,在開頭加上
{% load static %}
然後將<link href=修改為本地路徑
具體如下
{% load static %}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 上述meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<!-- Bootstrap CSS -->
<link href="{% static 'login/css/bootstrap.min.css' %}" rel="stylesheet">
<title>登入</title>
</head>
<body>
<div class="container">
<div class="col">
<form class="form-login" action="/login/" method="post">
<h3 class="text-center">歡迎登入</h3>
<div class="form-group">
<label for="id_username">使用者名稱:</label>
<input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
</div>
<div class="form-group">
<label for="id_password">密碼:</label>
<input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required>
</div>
<div>
<a href="/register/" class="text-success "><ins>新使用者註冊</ins></a>
<button type="submit" class="btn btn-primary float-right">登入</button>
</div>
</form>
</div>
</div> <!-- /container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{# 以下三者的引用順序是固定的#}
<script src="{% static 'login/css/jquery.js' %}"></script>
<script src="{% static 'login/css/popper.js' %}"></script>
<script src="{% static 'login/css/bootstrap.min.js' %}"></script>
</body>
</html>
然後新增一個背景圖片
在/login/static/login
目錄下建立一個image目錄,css中新增我們為登入檢視寫的css檔案,這裡是login.css
,image目錄中,拷貝進來你想要的背景圖片,這裡是bg.jpg
。最終目錄結構如下:
下面我們修改一下login.html的程式碼,主要是引入了login.css檔案,注意最開頭的{% load static %}
,表示我們要載入靜態檔案。
{% load static %}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 上述meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<!-- Bootstrap CSS -->
<link href="{% static 'login/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'login/css/login.css' %}" rel="stylesheet"/>
<title>登入</title>
</head>
<body>
<div class="container">
<div class="col">
<form class="form-login" action="/login/" method="post">
<h3 class="text-center">歡迎登入</h3>
<div class="form-group">
<label for="id_username">使用者名稱:</label>
<input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
</div>
<div class="form-group">
<label for="id_password">密碼:</label>
<input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required>
</div>
<div>
<a href="/register/" class="text-success "><ins>新使用者註冊</ins></a>
<button type="submit" class="btn btn-primary float-right">登入</button>
</div>
</form>
</div>
</div> <!-- /container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{# 以下三者的引用順序是固定的#}
<script src="{% static 'login/css/jquery.js' %}"></script>
<script src="{% static 'login/css/popper.js' %}"></script>
<script src="{% static 'login/css/bootstrap.min.js' %}"></script>
</body>
</html>
其實就是在引用bootstrap.min.css下面加了一句
login.css和其他css在一個資料夾內,login.css如下:
body {
height: 100%;
background-image: url('../image/bg.jpg');
background-repeat: no-repeat;
background-size: cover;
}
.form-login {
width: 100%;
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-login{
margin-top:80px;
font-weight: 400;
}
.form-login .form-control {
position: relative;
box-sizing: border-box;
height: auto;
padding: 10px;
font-size: 16px;
}
.form-login .form-control:focus {
z-index: 2;
}
.form-login input[type="text"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-login input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
form a{
display: inline-block;
margin-top:25px;
font-size: 12px;
line-height: 10px;
}
使用任意的一個bg.jpg即可
下面的是我的登入介面
至此,資料模型和login的前端介面都做好了,但是還有事情要做
根據我們在路由中的設計,使用者通過login.html
中的表單填寫使用者名稱和密碼,並以POST的方式傳送到伺服器的/login/
地址。伺服器通過login/views.py
中的login()
檢視函式,接收並處理這一請求。
我們可以通過下面的方法接收和處理請求:
def login(request): if request.method == "POST": username = request.POST.get('username') password = request.POST.get('password') print(username, password) return redirect('/index/') return render(request, 'login/login.html')
但此時輸入賬戶密碼會報錯
錯誤原因是CSRF驗證失敗,請求被中斷。CSRF(Cross-site request forgery)跨站請求偽造,是一種常見的網路攻擊手段,具體原理和技術內容請自行百科。Django自帶對許多常見攻擊手段的防禦機制,CSRF就是其中一種,還有XSS、SQL注入等。
解決這個問題的辦法其實在Django的Debug錯誤頁面已經給出了,我們需要在前端頁面的form表單內新增一個{% csrf_token %}
標籤:
<div class="container">
<div class="col">
<form class="form-login" action="/login/" method="post">
{% csrf_token %}
<h3 class="text-center">歡迎登入</h3>
<div class="form-group">
<label for="id_username">使用者名稱:</label>
<input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
</div>
<div class="form-group">
<label for="id_password">密碼:</label>
這個標籤必須放在form表單內部,但是內部的位置可以隨意。
重新重新整理login頁面,確保csrf的標籤生效,然後再次輸入內容並提交。這次就可以成功地在Pycharm開發環境中看到接收的使用者名稱和密碼,同時瀏覽器頁面也跳轉到了首頁。但是此時沒有進行任何密碼驗證的,意思是隨便輸入什麼都可以跳轉到主頁,接下來我們再設定一下密碼驗證.
下面貼出當前狀態下,/login/views.py中的全部程式碼,注意其中添加了一句from . import models
,匯入我們先前編寫好的model模型。
from django.shortcuts import render from django.shortcuts import redirect from . import models # Create your views here. def index(request): pass return render(request, 'login/index.html') def login(request): if request.method == "POST": username = request.POST.get('username') password = request.POST.get('password') if username.strip() and password: # 確保使用者名稱和密碼都不為空 # 使用者名稱字符合法性驗證 # 密碼長度驗證 # 更多的其它驗證..... try: user = models.User.objects.get(name=username) except: return render(request, 'login/login.html') if user.password == password: return redirect('/index/') return render(request, 'login/login.html') def register(request): pass return render(request, 'login/register.html') def logout(request): pass return redirect("/login/")
上面的程式碼還缺少很重要的一部分內容,也就是錯誤提示資訊!無論是登入成功還是失敗,使用者都沒有得到任何提示資訊,這顯然是不行的。
修改一下login檢視:
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') message = '請檢查填寫的內容!' if username.strip() and password: # 使用者名稱字符合法性驗證 # 密碼長度驗證 # 更多的其它驗證..... try: user = models.User.objects.get(name=username) except : message = '使用者不存在!' return render(request, 'login/login.html', {'message': message}) if user.password == password: print(username, password) return redirect('/index/') else: message = '密碼不正確!' return render(request, 'login/login.html', {'message': message}) else: return render(request, 'login/login.html', {'message': message}) return render(request, 'login/login.html')
請仔細分析一下上面的登入和密碼驗證邏輯,以及錯誤提示的安排。
這裡增加了message變數,用於儲存提示資訊。當有錯誤資訊的時候,將錯誤資訊打包成一個字典,然後作為第三個引數提供給render方法。這個資料字典在渲染模板的時候會傳遞到模板裡供你呼叫。
為了在前端頁面顯示資訊,還需要對login.html
進行修改:
<form class="form-login" action="/login/" method="post">
{% if message %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
{% csrf_token %}
<h3 class="text-center">歡迎登入</h3>
<div class="form-group">
<label for="id_username">使用者名稱:</label>
<input type="text" name='username' class="form-control" id="id_username" placeholder="Username" autofocus required>
</div>
<div class="form-group">
<label for="id_password">密碼:</label>
<input type="password" name='password' class="form-control" id="id_password" placeholder="Password" required>
</div>
<div>
<a href="/register/" class="text-success " ><ins>新使用者註冊</ins></a>
<button type="submit" class="btn btn-primary float-right">登入</button>
</div>
</form>
Django的模板語言{% if xxx %}{% endif %}
非常類似Python的if語句,也可以新增{% else %}
分句。例子中,通過判斷message變數是否為空,也就是是否有錯誤提示資訊,如果有,就顯示出來!這裡使用了Bootstrap的警示資訊類alert,你也可以自定義CSS或者JS。
好了,重啟伺服器,嘗試用錯誤的和正確的使用者名稱及密碼登入,看看頁面效果吧!下面是錯誤資訊的展示:
但是這種驗證的方式太麻煩了,這裡提供一個更簡單的方式
在專案根目錄的login資料夾下,新建一個forms.py
檔案,也就是/login/forms.py
,又是我們熟悉的Django組織檔案的套路,一個app一套班子!
在/login/forms.py
中寫入下面的程式碼,是不是有一種編寫資料model模型的既視感?
from django import forms class UserForm(forms.Form): username = forms.CharField(label="使用者名稱", max_length=128) password = forms.CharField(label="密碼", max_length=256, widget=forms.PasswordInput)
使用了Django的表單後,就要在檢視中進行相應的修改:
# login/views.py from django.shortcuts import render from django.shortcuts import redirect from . import models from . import forms # Create your views here. def index(request): pass return render(request, 'login/index.html') def login(request): if request.method == 'POST': login_form = forms.UserForm(request.POST) message = '請檢查填寫的內容!' if login_form.is_valid(): username = login_form.cleaned_data.get('username') password = login_form.cleaned_data.get('password') try: user = models.User.objects.get(name=username) except : message = '使用者不存在!' return render(request, 'login/login.html', locals()) if user.password == password: return redirect('/index/') else: message = '密碼不正確!' return render(request, 'login/login.html', locals()) else: return render(request, 'login/login.html', locals()) login_form = forms.UserForm() return render(request, 'login/login.html', locals()) def register(request): pass return render(request, 'login/register.html') def logout(request): pass return redirect("/login/")
Django的表單很重要的一個功能就是自動生成HTML的form表單內容。現在,我們需要修改一下原來的login.html
檔案:
{% load static %}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 上述meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<!-- Bootstrap CSS -->
<link href="{% static 'login/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'login/css/login.css' %}" rel="stylesheet"/>
<title>登入</title>
</head>
<body>
<div class="container">
<div class="col">
<form class="form-login" action="/login/" method="post">
{% if message %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
{% csrf_token %}
<h3 class="text-center">歡迎登入</h3>
{{ login_form }}
<div>
<a href="/register/" class="text-success "><ins>新使用者註冊</ins></a>
<button type="submit" class="btn btn-primary float-right">登入</button>
</div>
</form>
</div>
</div> <!-- /container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{# 以下三者的引用順序是固定的#}
<script src="{% static 'login/css/jquery.js' %}"></script>
<script src="{% static 'login/css/popper.js' %}"></script>
<script src="{% static 'login/css/bootstrap.min.js' %}"></script>
</body>
</html>
重新啟動伺服器,會有點亂碼
這裡我們需要手動渲染欄位,將之前的{{ login_form }}替換為
<div class="form-group">
{{ login_form.username.label_tag }}
{{ login_form.username}}
</div>
<div class="form-group">
{{ login_form.password.label_tag }}
{{ login_form.password }}
</div>
然後在form類裡新增attr屬性即可,如下所示修改login/forms.py
from django import forms
class UserForm(forms.Form):
username = forms.CharField(label="使用者名稱", max_length=128, widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': "Username",'autofocus': ''}))
password = forms.CharField(label="密碼", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control','placeholder': "Password"}))
重新整理後介面就恢復正常了
接下來就是使用session了
首先,修改login/views.py
中的login()檢視函式:
def login(request):
if request.session.get('is_login', None): # 不允許重複登入
return redirect('/index/')
if request.method == 'POST':
login_form = forms.UserForm(request.POST)
message = '請檢查填寫的內容!'
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
try:
user = models.User.objects.get(name=username)
except :
message = '使用者不存在!'
return render(request, 'login/login.html', locals())
if user.password == password:
request.session['is_login'] = True
request.session['user_id'] = user.id
request.session['user_name'] = user.name
return redirect('/index/')
else:
message = '密碼不正確!'
return render(request, 'login/login.html', locals())
else:
return render(request, 'login/login.html', locals())
login_form = forms.UserForm()
return render(request, 'login/login.html', locals())
既然有了session記錄使用者登入狀態,那麼就可以完善我們的登出檢視函數了:
def logout(request): if not request.session.get('is_login', None): # 如果本來就未登入,也就沒有登出一說 return redirect("/login/") request.session.flush() # 或者使用下面的方法 # del request.session['is_login'] # del request.session['user_id'] # del request.session['user_name'] return redirect("/login/")
然後修改index檢視函式,新增相關限制:
def index(request): if not request.session.get('is_login', None): return redirect('/login/') return render(request, 'login/index.html')
現在只要之前登入過,就是,在瀏覽器輸入login也是會直接跳轉到index了,至此