Python+Django後臺互動
MVC,MVT概念:
MVC:
M全拼model 主要封裝資料庫的訪問,對資料庫中的資料庫進行增,刪,改,查操作。
V全拼view用於封裝結果,生成頁面展示的的HTML內容。
C全拼controller用於接收請求處理業務邏輯與model和view進行互動返回結果。
MVT:
M全拼model 與mvc的m功能相同,負責和資料庫互動,進行資料處理。
V全拼view 與mvc中的c功能相同,接收請求,進行業務處理,返回應答。
T全拼template 與mvc中的v功能相同,負責封裝構造返回html。
安裝步驟:
安裝虛擬環境:
第一條命令:
sudo pip install virtualenv
第二條命令:
sudo pip install virtualenvwrapper
上述不能執行使用第二種方法:
第一條命令:
sudo python3 -m pip install virtualenv
第二條命令:
sudo python3 -m pip install virtualenvwrapper
如果下載速度慢:
可以在命令後面加豆瓣源:
新增一個豆瓣源: -i https://pypi.douban.com/simple
- 新增三句話(家目錄下面的 .bashrc 如果你是用zsh 新增到.zshrc ) 要讓我們的配置生效 soure .bashrc soure .zshrc
作用: 指定我們預設Python直譯器的位置,指定我們virtualenvwrapper.sh的位置,python軟體包和直譯器安裝的位置
如果看不懂詳見:https://www.jianshu.com/p/6a34c1baee6a
用法:
建立虛擬環境:
mkvirtualenv + 虛擬環境名字 -p + python版本
p:後面加python版本可以不寫
檢視所有虛擬環境:
workon
切換虛擬環境:
workon + 要切換的虛擬環境名
刪除虛擬環境:
rmvirtualenv + 要刪除的虛擬環境名
退出虛擬環境:
deactivate
需要安裝軟體包Django:
pip install django==1.11
因為安裝 django 1.11比較穩定
開始建立我們的第一個django專案:
建立專案:
django-admin startproject + 專案名稱
專案結構:
python
manage.py #用於管理整個專案的核心模組
會有一個python包(包名和專案同名)
settings.py #專案的路由模組
urls.py #專案的路由模組
wsgi.py #django輕量級伺服器
test.py #用於寫單元測試的模組
建立應用:
1.需要先進入到那個目錄下面
2.進入專案的目錄下面輸入命令
python manage.py startapp + 應用名
應用結構:
會有一個之前建立的應用包 包含:
models.py #模型 用於建立模型 跟資料庫互動
view.py #接收請求,處理返回的結果模組
admin.py #後臺管理站點
tests.py #測試模組
migrations(資料夾,python包)生成的遷移檔案
__init__.py 第一次執行遷移這裡會生成記錄
手動注意點: 1. 使用pycharm開啟 專案的時候需要吧應用安裝到專案裡面
INSTALL_APPS—-> booktest
2. 虛擬環境 我們切換成 我們需要的那個虛擬環境
3. template 資料夾(手動沒有這個檔案)手動建立一個這樣的資料夾
需要去 settings.py 模組裡面 把這個資料夾的地址 配置進來
templates 未來我們放html檔案地方
用pycharm 也可以直接建立 專案和應用 並且相關的配置 它都給你做好了 上手即用
版本: pro 專業版
在配置檔案裡面,可以把我們的專案展示出來的內容由英文變成中文
LANGUAGE_CODE = 'zh-hans' # zh-Hans 繁體
TIME_ZONE = 'Asia/Shanghai'
ORM:
django裡面有一個模組model.py 類對應資料庫裡面一張表,物件對應資料庫裡面的一橫資料
例:
class Person(models.Model):
book = models.CharFiled(max_length=20)
Person 對應資料庫裡面的一張表
p = Person() 一條資料
案例:
from django.db import models
# django模組代表代表從django.db匯入models模型
from datetime import datetime #匯入時間模組
class BookInfo(models.Model):
bname = models.CharField(max_length=20)
bpub_date =models.CharField(default=datetime.now)
繼承自models.Model去寫我們自己的內容
CharField 代表 varchar型別
max_length 代表 最大長度
生成遷移檔案:
python manage.py makemigrations
執行遷移檔案:
python manage.py migrate
建立超級使用者及站點管理:
後臺管理 站點管理—>其實就是在管理你的資料庫 通過介面而不是程式碼或者 sql語句
建立一個超級管理員
python manage.py createsuperuser
將你的專案 python manage.py runserver 跑起來
後臺如果沒有顯示 各種模型 先去admin.py 檔案裡面 匯入模型
將模型註冊到後臺頁面
簡單操作
python manage.py shell
- 匯入對應的模型的模組
- 寫程式碼 用django這個框架提供方式 來操資料庫
# 往資料庫裡面寫
1. 例項化一個物件 (模型-->表)
b = BookInfo()
2. 物件名.欄位名 新增資料
b.bname = '射鵰英雄傳'
3. 儲存操作的資料
b.save()
# 讀
BookInfo.objects.all() # 列表,
模型類的名字.objects.all()是獲取資料庫裡面所有的行——> 列表(裡面裝的是一個個物件)
模型類的名字.objects.get(id=1)是獲取資料庫裡面的id=1的哪一條資料 —-> 物件
每一個物件 就是資料庫裡面的一行資料
小總結:
1. 模型類(model.py)
對應關係 類—-> 表 物件—-> 表裡面一行
2. 你用Python寫完一個類 不意味著資料庫裡面就有資料
1> 生成遷移檔案
2> 執行遷移檔案
3. 最最簡單操作 通過 shell指令碼來 臨時
1. 新增
1> 匯入模組(你要的模型類)
2> 新增 例項化一個物件 通過物件名.屬性名 就可以新增一條資料 但是 在資料庫裡面 沒有新增成功 因為 要 儲存 物件名.save()
3. all get
模型類類名.objects.all()—>獲取所有資料
模型類類名.objects.get(條件)—-> 滿足條件的某一條資料
查詢集表示從資料庫中獲取的物件集合,在管理器上呼叫某些過濾器方法會返回查詢集,查詢集可以含有零個、一個或多個過濾器。過濾器基於所給的引數限制查詢的結果,從Sql的角度,查詢集和select語句等價,過濾器像where和limit子句。
返回查詢集的過濾器如下:
all()返回所有資料
filter()返回滿足條件的資料
exclude()返回滿足條件之外的資料,相當於SQL語句中where部分的not關鍵字
order_by()對結果進行排序
返回單個值的過濾器如下:
get()代表返回返回單個滿足條件
count()返回當前查詢結果的總數
aggregate()聚合 返回一個字典
利用AJAX獲取get請求實現非同步請求返回結果案例演示:
首先我們在pycharm的templates檔案裡建立兩個html的模板 名字可以隨便起 在案例中我們把兩個名字一個設為json1.html和json2.html
如圖:
緊接著我們在views.py檔案中設定兩個python函式來為templates展示頁面
如圖:
匯入JsonResponse 它是HttpResponse的子選項
第一個函式代表獲取資料
第二個函式代表返回結果
然後我們去配置這兩個函式的路由也就是urls.py檔案:
如圖:
我們進入urls.py首先要做的第一件事情是要在book應用下匯入views的檔案資料(因為本人建的是book應用,我們在應用下面的urls.py去設定路由)
在這裡我們運用到了反向解析這樣使得路由地址更清晰更安全更簡潔
這時我們就要在templates的兩個模板裡面去運用ajax去寫我們的模板並實現非同步請求及結果
我們首先在json1.html檔案上進行書寫
首先我們要配置jQuery的CDN 由於我們要方便簡潔就可以在這裡找到地址 但是重要的是每一次專案都必須聯網
找到版本進行復制到json1.html中
接下來我們開始在json1.html繪製內容:
我們首先要在body標籤中去設定內容 這個配置流程就和我們平時寫前端頁面一樣
button代表按鈕 是我們即將用ajax獲取結果的總指揮官
id為account和pwd代表利用ajax獲取的賬號密碼結果之前的提示
那麼我們去演示一下這個頁面的概要資訊
接著我們開始書寫最重要的ajax的內容這時我會把每一個步驟的圖片截下來翻譯一遍請大家用心去看,其實學會了領略意思是非常簡單的
首先我們要寫一個script的標籤在裡面去寫這個 那麼我們看到這個會覺得有點亂
所以我們在每一次碰到$的時候後面都會加一對括號就像這樣$() 然後在括號裡
寫上function(){}就像這樣
這樣就會形成
$(function(){
})
這段話的含義是接收上下文 據我感覺就是上文的cdn下文的body 這樣才能接收
並使用
這時我們開始寫button把總指揮給寫出來
首先我們寫$()在括號裡寫$('#action')代表我們在body寫的按鈕在這裡去
相互連線 然後後面要寫監聽事件在滑鼠點選的時候會反饋一個請求
$('#action').click() 緊接著在.click()的括號裡寫入function(){}這
代表回撥函式把function裡面的內容來給.click去支配 當我們點選 就會產
生這個請求$('#action').click(function(){
})
接下來我們要在回撥函式的括號內用get請求獲取view裡的配置內容在json2.html來呈現結果
我們用反向解析的形式來配置json2的路徑 此時大家會想 那json2在模板中寫不寫內容
其實不用因為我們早在view.py的檔案中json2是JsonResponse來返回結果的的
當我們每一次點選按鈕時會呈現json2的結果 由於我們沒有在json2裡設定內容所以顯示的是空白
所以我們進行下一步操作
當我們獲取get請求時 利用回撥函式返回我們data也就是說我們在回撥函式裡面的資料 所以我們要把body裡面的account和pwd利用.html函式去返回view裡資料a的內容 和資料b的內容
這時我們去執行一下
所以我們在點選按鈕的時候發出了一個get請求獲取了view裡的a資料和b資料
並用非同步請求展現出來
cookie和session的區別:
cookie 目的是記錄狀態(會話保持) cookie代表 客戶端 —> 向伺服器發出請求 伺服器響應請求(並設定瀏覽器的cookie值) 例: name = ‘zhangsan’ 當客戶端又一次 發出請求時並帶上 name=’zhangsan’ 傳送到伺服器 那麼我們伺服器 接收請求後就知道伺服器裡面的內容 是name=’zhangsan’
cookie的缺點 cookie的鍵和值都存在瀏覽器的客戶端裡面 意味著安全性不高 本地可以有辦法隨意篡改
session 代表 客戶端 向伺服器發起請求 這時候伺服器會有一張表 表裡有兩個欄位 一個是 session的id 一個是session的值 然後在瀏覽器本地存了 一個cookie 這個cookie的鍵 是session id的值 當客戶端又一次發起請求時 就帶上這個上這個 session id
django登入實戰
我們首先在pycharm建立新的一個專案和應用 專案名叫login_login 應用名叫login_user請看下圖:
然後就create建立專案和應用
在mysql裡面建立一個數據庫為了儲存您的賬號密碼等資料如下圖:
建立了一個名叫loginA的資料庫
然後我們進行settings的相關配置:
我們開始在models.py建立表的模型:
在這個模型中我們要設計 使用者名稱,密碼,郵箱地址,性別,建立時間
#設計一個User的模型類
class User(models.Model):
#設計一個元祖來給性別傳值
gender = (
('boy', '男孩'),
('gril', '女孩')
)
#設計使用者名稱 最大長度為128 站點管理顯示使用者名稱欄位 欄位unique唯一不得重複
name = models.CharField(max_length=128, verbose_name='使用者名稱', unique=True)
#設計密碼 最大長度為256 因為可能會關係到加密問題所以在資料庫裡把字元調的長了一些
password = models.CharField(max_length=256, verbose_name='密碼')
#設計郵箱 使用專門的EmailField型別
email = models.EmailField(verbose_name='郵箱')
#設計性別 把之前的gender利用choices來接收 設定字元長度10 預設為男
sex = models.CharField(max_length=10, choices=gender, default='男', verbose_name='性別')
#設計建立時間 使用專門的DateTimeField欄位去設定
t_time = models.DateTimeField(auto_now_add=True, verbose_name='時間')
#人性化設計使用者名稱 方便在站點管理顯示
def __str__(self):
return self.name
#設計Meta元資訊 名字為使用者表 複數形式也等於使用者表
class Meta:
verbose_name = '使用者表'
verbose_name_plural = verbose_name
在專案包下的 init檔案中設定 與pymysql的連結配置如下圖:
隨後我們在下方Terminal終端中輸入命令 第一條命令代表 生成遷移 代表 把剛剛models.py設計的模型表 和一系列配置進行當前的生成 但是 這個是生成不帶表 已經執行
緊接著我們進行執行遷移
全是OK代表就是成功的
然後開始建立站點管理的超級使用者
我們在應用下的admin.py中註冊我們的模型表
首先匯入應用下的models模型下的User應用
from .models import User
然後註冊User模型
admin.site.register(User)
我們用命令開始登入伺服器
用伺服器地址登入admin
為了能讓使用者看到我們展示的頁面 所以我們在templates檔案中建立 4個html檔案 這時我們選中templates右鍵 new 找到html 點選 會出現小框 一個一個就這樣建立
這四個檔案 base.html代表父模板 剩下的三個網頁都要繼承base.html 其中 這三個檔案 index.html代表首頁 login.html代表登入頁 register.html代表註冊頁
然後開始設定應用下的views.py
#首先匯入模型下的User表
from .models import User
#匯入重定向
from django.shortcuts import redirect
#建立index首頁函式 return返回首頁前端模板
def index(request):
return render(request, 'index.html')
#建立login登入函式 return返回登入頁前端模板
def login(request):
return render(request, 'login.html')
#建立register註冊函式 return返回註冊頁前端模板
def register(request):
return render(request, 'register.html')
#建立logout退出登入函式 return返回首頁前端模板
def logout(request):
#重定向 退出登入直接跳轉到首頁
return register('/index/')
然後我們開始在目錄的檔案下設定三個 html的路由配置
從應用下匯入 view
from login_user import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
配置view的四個路由
url(r'^index/$',views.index),
url(r'^register/$',views.register),
url(r'^login/$',views.login),
url(r'^logout/$',views.logout)
]
隨後我們在templates檔案裡面找到base.html 我們把他稱作父模板 其他模板都繼承他所以要幹好多事情 首先我們要在這個模板中 寫一個 導航條 和 登入註冊的輸入框
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3個meta標籤*必須*放在最前面,任何其他內容都*必須*跟隨其後! -->
<title>{% block title %}
首頁
{% endblock %}</title>
<!-- Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav"
aria-expanded="false">
<span class="sr-only">切換導航條</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Mysite</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="my-nav">
<ul class="nav navbar-nav">
<li class="active"><a href="#">主頁</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">登入</a></li>
<li><a href="#">註冊</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
當子模板繼承時 在這裡設定block覆蓋這裡的內容
{% block content %}
{% endblock %}
{% block custom_css %}
{% endblock %}
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
有不懂這端程式碼詳見:https://v3.bootcss.com/components/#navbar
然後我們用login.html繼承base.html 在login.html寫入繼承base.html的模板 在block content 寫了一個登入註冊的form表單輸入框 這裡的 action=’/login/’ method=’post’ 當用戶提交請求時 action會跳轉到view裡的login發出post請求:
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}登入{% endblock %}
{% block css %}
<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-4 col-md-offset-4">
<form class='form-login' action="/login/" method="post">
<h2 class="text-center">歡迎登入</h2>
<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>
<button type="reset" class="btn btn-default pull-left">重置</button>
<button type="submit" class="btn btn-primary pull-right">提交</button>
</form>
</div>
</div> <!-- /container -->
{% endblock %}
然後我們執行下伺服器 看可不可以出現我們想象的介面
緊接著我們就開始繪製我們應用中的views.py裡面的登入函式
含義:
def login(request):
#如果前端模板提交的是post請求 就執行以下操作
if request.method == 'POST':
#獲取前端輸入的使用者名稱 和 密碼
username = request.POST.get('username',None)
password = request.POST.get('password',None)
#測試以下將賬號密碼打印出來 看有沒有獲取到
print(username,password)
#否則 當輸入地址時跳轉到登入頁面
else:
return render(request,'login.html')
我們利用Pycharm的 Debug模式來測試前端傳過來的值 並用print列印 看看有沒有傳過來
首先 點選右上角的蟲子
其次 給選擇感覺有疑義的一橫程式碼打個紅點 方便檢測
最後 我們開啟執行我們的程式碼 點選蟲子旁邊的左2 按鈕開始
我們輸入地址 開啟我們的前端登入頁面 點選提交
我們輸入賬號是 zhangsan 密碼 123456
會出現禁止訪問 csrf 安全 這是正確的
我們要在前端頁面的form表單中加入csrf_token 請看程式碼
<form class='form-login' action="/login/" method="post">
加在這裡
{% csrf_token %}
<h2 class="text-center">歡迎登入</h2>
<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>
<button type="reset" class="btn btn-default pull-left">重置</button>
<button type="submit" class="btn btn-primary pull-right">提交</button>
</form>
然後 我們重新重新整理頁面 我們寫一個跳到首頁 我們的值就傳過來了 很成功
我們開始接著寫我們的邏輯 在寫邏輯之前我們先回顧一下 首先 我們 在login 這個函式中 要寫我們登入的內容 我們設立了一個判斷 為了更加節省我們的程式碼 在程式碼中 我們設計 if request.method == ‘POST’這個代表 如果我們找到前端用POST發起了傳值的請求並跳轉到 我們這個函式中 我們就執行 POST的以下操作 在程式碼中我們看到 username = request.PoST.get(‘username’,None)和password = request.PoST.get(‘password ‘,None)代表 在前端我們傳過來的賬號密碼 用兩個變數來接收 這兩個變數分別是username password 然後測試一下列印這兩個變數裡的值 並跳轉到 首頁
否則中的return render(request,‘login.html’)代表當輸入地址時跳轉的登入頁
所以我們就在POST登入中寫效驗的功能
def login(request):
if request.method == 'POST':
#我們在這裡設計訊息 等於空字元方便 判斷時使用
message = ''
username = request.POST.get('username',None)
password = request.POST.get('password',None)
#如果 賬號密碼
if username and password:
#將賬號去除空格 並傳給 username變數
username = username.strip()
#捕捉異常
try:
#獲取資料庫裡User的表裡的一條資訊 用name欄位對比 剛剛去除空格的username裡的值
user = User.objects.get(name=username)
#如果 資料庫裡的密碼 等於 前端傳來的密碼
if user.password == password:
#就重定向跳轉到首頁
return redirect('/index/')
#否則
else:
#密碼錯誤 並跳轉到登入介面 並列印 密碼錯誤提示
message = '密碼錯誤'
return render(request, 'login.html', {'message': message})
#除非
except:
#該使用者不存在 並跳轉到登入頁 列印 該使用者不存在
message = '該使用者名稱不存在'
return render(request, 'login.html', {'message': message})
#賬號密碼都正確並跳轉到首頁
return redirect('/index/')
else:
return render(request,'login.html')
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}登入{% endblock %}
{% block css %}
<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-4 col-md-offset-4">
<form class='form-login' action="/login/" method="post">