完成一個完整的網頁服務,須要有如下:html
再次回顧一下Django 的完成開發流程:python
一些值的獲取:mysql
對於性別,爲互斥屬性:sql
愛好則爲多選:數據庫
須要使用新的方法 getlist 來獲取多個愛好:django
單選下拉框選擇獲取:app
多選下拉框也須要用到getlist 函數
對於上傳文件的設置:post
1 首先form 表單要設置特殊屬性:學習
2 文件上傳使用新的方法:
使用chunks 來一點一點獲取數據:
上傳文件到指定目錄:
總結一下經常使用的方法:
而後來實踐一下,把上面的所有實現一下:
views:
from django.shortcuts import render,redirect,HttpResponse # Create your views here. def user(request): print('user') if request.method == 'GET': return render(request,'user.html') elif request.method == 'POST': #用戶名 u = request.POST.get('user') #密碼 p = request.POST.get('pwd') #性別 g = request.POST.get('gender') #城市 c = request.POST.get('city') #愛好 f = request.POST.getlist('favor') print(u,p,g,c,f) #文件是一個對象,能夠查看對象,大小等 f_obj = request.FILES.get('up_head_img') #獲取文件名 f_name = f_obj.name f_size = f_obj.size print(f_name,f_size) #真正接收並存到本地 import os file_path = os.path.join('upload',f_obj.name) block_size = 0 with open(file_path,mode='wb') as f: for block in f_obj.chunks(): #用這個來獲取的當前已經上傳了多少,能夠給用戶返回 block_size += len(block) print(block_size) f.write(block) print(f_obj.name,'傳完了') return HttpResponse('200')
urls:
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/" method="POST" enctype="multipart/form-data"> <div class="text"> <label>用戶名</label> <input type="text" name="user"/> <label>密碼</label> <input type="password" name="pwd"/> </div> <div class="chose"> <div> <label>性別</label> <input type="radio" name="gender" value="1"/>男 <input type="radio" name="gender" value="2"/>女 </div> <div> <label>城市</label> <select name="city"> <option value="sh">上海</option> <option value="bj">北京</option> <option value="tj">天津</option> <option value="sjz">石家莊</option> </select> </div> <div> <label>愛好</label> <input type="checkbox" name="favor" value="1"/>騎行 <input type="checkbox" name="favor" value="2"/>旅遊 <input type="checkbox" name="favor" value="3"/>音樂 <input type="checkbox" name="favor" value="4"/>電影 <input type="checkbox" name="favor" value="5"/>把妹 <input type="checkbox" name="favor" value="6"/>吃吃吃 </div> </div> <div class="upload"> <label>上傳頭像</label> <input type="file" name="up_head_img"/> </div> <input type="submit" value="提交全部數據"/> </form> </body> </html>
效果:
Django 有兩種方式:
1 FBV
function base view
function函數處理的方式
2 CBV
class base view
class類處理的方式
寫一個類處理的方式:
1 先導入View 模塊
2 定義類及裏面的屬性
3 定義url:
4 html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <form action="/home/" method="POST"> <h1>測試Class 處理方式 CBV</h1> <input type="submit" value="測試提交方法"/> </form> </div> </body> </html>
5 測試:
在這裏咱們能夠實現一個相似裝飾器的功能,就是在類裏的方法執行前或後添加一些其餘功能:
使用dispatch 函數:
from django.views import View class Home(View): def dispatch(self, request, *args, **kwargs): #調用父類中的 print('訪問前要執行的') result = super(Home,self).dispatch(request,*args,**kwargs) print('訪問後要執行的') return result def get(self,request): print('使用方法:', request.method) return render(request,'home.html') def post(self,request): print('使用方法:',request.method) return render(request, 'home.html')
測試:
以上爲經常使用的方法。
下面學習下模板語言:
1 在html 中如何循環得道的字典數據呢?
實踐:
views:
USER_DICT = { 'k1': 'root1', 'k2': 'root2', 'k3': 'root3', 'k4': 'root4', 'k5': 'root5', } def moban(request): return render(request,'moban.html',{'USER_DICT':USER_DICT})
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <span>測試for 循環 只循環key</span> <ul> {% for k in USER_DICT.keys %} <li>{{ k }}</li> {% endfor %} </ul> </div> <div> <span>測試for 循環 只循環value</span> <ul> {% for v in USER_DICT.values %} <li>{{ v }}</li> {% endfor %} </ul> </div> <div> <span>測試for 循環 所有循環</span> <ul> <li>k -- v</li> {% for k,v in USER_DICT.items %} <li>{{ k }} -- {{ v }}</li> {% endfor %} </ul> </div> </body> </html>
urls:
from user import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user/', views.user), url(r'^home/', views.Home.as_view()), url(r'^moban/', views.moban), ]
效果:
下面實現一個稍微複雜一點的:
1 列出字典的k及value裏的一個值
views:
USER_INFO = { '1': {'name':'shenyang','age':25,'mail':'123@qq.com'}, '2': {'name':'wang','age':18,'mail':'456@qq.com'}, '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'}, '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'}, } def list(request): return render(request,'list.html',{'USER_INFO':USER_INFO})
urls:
url(r'^list/', views.list),
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用戶列表</h1> <div> <ul> {% for k,v in USER_INFO.items %} <li><a target="_blank" href="/detail-{{ k }}.html">{{ k }} -- {{ v.name }}</a></li> {% endfor %} </ul> </div> </body> </html>
效果:
2 實現經過點擊鏈接,進入新的網頁並顯示value裏的全部值
用到的點有:
1 url的正則匹配
2 經過url的數據定位某一個數據
views:
USER_INFO = { '1': {'name':'shenyang','age':25,'mail':'123@qq.com'}, '2': {'name':'wang','age':18,'mail':'456@qq.com'}, '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'}, '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'}, } def list(request): return render(request,'list.html',{'USER_INFO':USER_INFO}) def detail(request,nid): detail_info = USER_INFO[nid] return render(request,'details.html',{'detail_info':detail_info})
urls:
from user import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user/', views.user), url(r'^home/', views.Home.as_view()), url(r'^moban/', views.moban), url(r'^list/', views.list), url(r'^detail-(?P<nid>\d+).html', views.detail), ]
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>詳細信息</h2> <div> <h6>用戶名:{{ detail_info.name }}</h6> <h6>年齡:{{ detail_info.age }}</h6> <h6>郵箱:{{ detail_info.mail }}</h6> </div> </body> </html>
效果:
咱們不只能夠經過url 獲取一個數據,還能獲取多個數據:
匹配規則:
匹配相似於 detail-1-2.html 這種兩個數字的:
函數獲取數據:
可是這樣有一個很差的就是當url中這兩個數字換了之後代碼裏的函數獲取的數據也就不正確了,因此須要給匹配到的指定一個變量,這樣就再也不須要關心順序了:
函數獲取數據:
無論順序,直接獲取:
nid 就是nid uid 就是uid
這裏很重要,總結一下:
路由系統,URL的三種方式:
1 直接匹配,不須要獲取數據:
2 經過正則匹配,可是在函數獲取數據時必須注意先後順序:
3 經過正則匹配到後不須要關心順序,可是url中須要指定變量名稱:
url不只能夠匹配數字,還能夠經過各類匹配,函數還能夠以字典方式和列表方式獲取數據:
例如函數中以字典方式獲取數據:
views:
def dic_test(request,**kwargs): print('This dic is: ',kwargs) nid = kwargs['nid'] uid = kwargs['uid'] all = 'This is ' + nid + ' and ' + uid return HttpResponse(all)
urls:
url(r'^dic_test-(?P<nid>\d+)-(?P<uid>\d+).html', views.dic_test),
html:
無
效果:
url 地址還能夠給一個變量,用於在html 模板中跳轉到指定變量的地址中:
固然若是想獲取絕對的url地址,使用:
由於在模板渲染的時候響應函數已經把全部的request 傳入,因此想獲取哪一個數據,只要request中有,就必定能獲取到,並渲染到模板中
另外一種方式本身跳轉到自定義頁面:
須要用到 reverse 模塊:
例如:
把name 爲 i2 的url 自定義一個url 經過列表形式轉換爲自定義url
urls:
viwes:
from django.urls import reverse def custom_url_i2(request,*args,**kwargs): print(request.path_info) url2 = reverse('i2',args=(8,12)) print(url2) return HttpResponse(url2)
效果:
把name 爲 i3 的url 自定義一個url 經過字典形式轉換爲自定義url
urls:
viwes:
def custom_url_i3(request,*args,**kwargs): print(request.path_info) url3 = reverse('i3',kwargs={'uid':88,'nid':66}) print(url3) return HttpResponse(url3)
效果:
總結一下:
固然上面這些是隻有Django 纔有的方式
路由系統中另外一個強大的功能叫作路由分發系統:
詳細來講就是經過指定一個url 到另外一個url路由文件就能夠實現多個項目與主路由的鬆耦合,這樣開發者能夠本身修改本身的項目的url地址而不會影響到其餘項目:
實現:
項目主urls:
user模塊urls:
user viwes:
host模塊urls:
host viwes:
效果:
路由系統暫時到此。
開始ORM:
ORM分爲兩類:
Django中的爲Codefirst
使用Django 建立一個用戶表:
1 寫類
from django.db import models # Create your models here. class User_info(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)
2 修改setting 添加app
3 執行命令生成表
python manage.py makemigrations python manage.py migrate
4 檢查
Django 建立表的時候表名爲:
app名_表的類名
這裏咱們在沒有作修改以前默認用的是SQLite數據庫,使用mysql 數據庫:
完整使用mysql 數據庫的步驟:
1 修改項目的__init__.py 添加pymysql
2 修改setting 使用mysql 鏈接
3 在app中寫一個類:
4 修改setting 註冊app
5 執行命令生成表
manage.py makemigrations manage.py migrate
6 查看錶:
配置完後學一下增刪改查:
1 增長:
a方式:
b方式:
以字典形式增長數據:
2 查:
查全部:
過濾(where)查詢:
這裏也是一個列表,由於用戶名稱等於root的可能有多個,因此要經過列表循環獲取數據
組合查詢(and條件):
雖然查到了一個可是查到的結果類型仍是一個列表,因此還要循環
3 刪除:
過濾刪除:
所有刪除:
.all().delete()
4 更新:
所有更新:
過濾更新:
實踐一下:
from host_manage import models def orm(request): # 增長 models.User_info.objects.create(username='root',password='123') # 查看 result = models.User_info.objects.all() for row in result: print(row.id,row.username,row.password) #刪除 models.User_info.objects.filter(username='alex').delete() #更新 models.User_info.objects.filter(id=2).update(password='66666') return HttpResponse('orm')
實現查詢的時候只拿取第一個,並返回一個對象:
first() 方法:
這樣查找以後就會取過濾後的第一個對象,這裏能夠判斷若是對象存在就說明有數據,若是爲None 則數據不存在
也能夠用下面的計數查詢,若是大於0說明有數據,可是不能獲取到多個信息,不經常使用:
還有一種獲取對象的方式,可是不推薦,須要配合try來使用:
查看真實的sql 語句,就是在操做對象時執行的sql:
寫一個列出和添加用戶的小功能:
1 views
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/')
2 models
from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)
3 urls
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), ]
4 html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用戶列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }}</li> {% endfor %} </ul> <input type="text" name="user" placeholder="用戶名" /></div> <div><input type="password" name="pwd" placeholder="密碼" /></div> <input type="submit" value="添加用戶"/> </form> </body> </html>
5 效果
繼續添加點擊用戶名能夠查看詳細信息功能:
使用url 的正則匹配形式:
1 views
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info})
2 urls
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), url(r'^userdetail-(?P<nid>\d+).html/',views.user_detail), ]
3 html
userinfo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用戶列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }} <a href="/user/userdetail-{{ i.id }}.html">詳細</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用戶名" /></div> <div><input type="password" name="pwd" placeholder="密碼" /></div> <input type="submit" value="添加用戶"/> </form> </body> </html>
userdetail
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> <li>{{ user_info.username }} -- {{ user_info.password }}</li> </ul> </body> </html>
4 效果
最後添加刪除和編輯功能:
1 刪除:
最簡單,根據id直接操做數據庫而後返回到用戶列表頁便可
2 修改:
返回指定id的數據到input 框,當修改後根據id提交
views:
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info}) def user_del(request,nid): print(nid) models.UserInfo.objects.filter(id=nid).delete() return redirect('/user/user_info/') def user_edit(request,nid): print(nid) if request.method =='GET': user = models.UserInfo.objects.filter(id=nid).first() return render(request,'useredit.html',{'user':user}) elif request.method == 'POST': u = request.POST.get('username') p = request.POST.get('password') print(u,p) models.UserInfo.objects.filter(id=nid).update(username=u,password=p) return redirect('/user/user_info/')
urls:
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), url(r'^userdetail-(?P<nid>\d+).html/',views.user_detail), url(r'^userdel-(?P<nid>\d+).html/',views.user_del), url(r'^useredit-(?P<nid>\d+).html/',views.user_edit), ]
html:
userinfo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用戶列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }} <a href="/user/userdetail-{{ i.id }}.html">詳細|</a><a href="/user/userdel-{{ i.id }}.html">刪除|</a><a href="/user/useredit-{{ i.id }}.html">編輯</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用戶名" /></div> <div><input type="password" name="pwd" placeholder="密碼" /></div> <input type="submit" value="添加用戶"/> </form> </body> </html>
useredit:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>修改用戶信息</h2> <form action="/user/useredit-{{ user.id }}.html/" method="POST"> <input type="text" name="nid" value="{{ user.id }}" style="display: none"/> <input type="text" name="username" value="{{ user.username }}"/> <input type="text" name="password" value="{{ user.password }}"/> <input type="submit" value="提交修改"/> </form> </body> </html>
效果:
基本的增刪改查就到這裏,下面說一下增長列和刪除列:
經過Django 的ORM 操做數據庫其實很簡單:
增長列:
1直接在class中增長一個屬性就行
2 執行命令,生成表結構:
刪除列:
1 直接註釋掉須要刪除的列
2 執行命令刪除
Django 中的ORM 有不少的數據類型,可是其本質也就是數據庫那幾種類型,只是Django 會幫你作一層驗證:
數據表的一些其餘操做:
指定列名:
創建索引:
創建惟一索引:
註冊時間,建立時間,但是使用這個:
下面這種纔會更新:
建立一個choices 類型的表:
Django 的admin 會自動看成選項:
存入數據庫的仍是數字,避免了連表查詢
總結一下字段的參數:
Django admin 顯示字段中文:
自定義幫助信息,在旁邊坐一個小的提示:
admin 的其餘一些方法:
實際上在數據庫中會生成 user_group_id 這個表
經過這個關聯鍵 獲取數據:
建立一個值:
直接寫入本地數據庫而不是跨表寫入
動態的下拉框:
實踐:
添加一個在建立用戶的時候指定組的功能,下拉框中的數據來自另外一個表的數據,存儲的時候直接存儲到本表。
先實現展現的功能:
models:
建立關聯的外鍵:
from django.db import models # Create your models here. class UserGroup(models.Model): uid = models.AutoField(primary_key=True) caption = models.CharField(max_length=32,unique=True) ctime = models.DateTimeField(auto_now_add=True,null=True) uptime = models.DateTimeField(auto_now=True,null=True) class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) user_group = models.ForeignKey('UserGroup',to_field='uid')
插入幾條數據,從新刷新一下數據庫,發現 userinfo表裏增長了一個 user_group_uid 的列,而不是user_group,這是由於外鍵關聯的是一個對象,而不是真正的列
views:
處理數據,在獲取組的時候使用外鍵的方式:
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() group_list = models.UserGroup.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list,'group_list':group_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') g = request.POST.get('group') print(u,p,g) models.UserInfo.objects.create(username=u,password=p,user_group_id=g) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info})
html:
info:
以點的方式繼續操做另外一張表
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用戶列表</h2> <ul> <li> 用戶名 -- 組</li> {% for i in user_list %} <li>{{ i.username }} -- {{ i.user_group.caption }} <a href="/user/userdetail-{{ i.id }}.html">詳細|</a><a href="/user/userdel-{{ i.id }}.html">刪除|</a><a href="/user/useredit-{{ i.id }}.html">編輯</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用戶名" /></div> <div><input type="password" name="pwd" placeholder="密碼" /></div> <div><select name="group" > {% for g in group_list %} <option value="{{ g.uid }}">{{ g.caption }}</option> {% endfor %} </select> </div> <input type="submit" value="添加用戶"/> </form> </body> </html>
detail:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> <li> 用戶名 -- 密碼 -- 組</li> <li>{{ user_info.username }} -- {{ user_info.password }} -- {{ user_info.user_group.caption }}</li> </ul> </body> </html>
效果: