day19 Dgango進階 路由系統及 ORM 詳解

 

完成一個完整的網頁服務,須要有如下: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分爲兩類:

1  DBfirst      先建立數據庫表結構  根據表結構自動生成類, 之後修改這個類就能夠修改數據庫
2  Codefirst   先寫代碼,寫好要建立的數據庫的表的類,而後自動生成表結構

 

 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 查:

  查全部:

   

    查到一個QuerySet 的格式的數據,直接理解爲是一個列表。
    列表中每個元素都是一個對象

 過濾(where)查詢:

   

   這裏也是一個列表,由於用戶名稱等於root的可能有多個,因此要經過列表循環獲取數據

 組合查詢(and條件):

   

   雖然查到了一個可是查到的結果類型仍是一個列表,因此還要循環

刪除:

  過濾刪除:

  

  所有刪除:

   .all().delete()

更新:

  所有更新:

  

  過濾更新:

  

 

實踐一下:

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>

效果:

 

相關文章
相關標籤/搜索