標籤:結構 計數 成功 strong 複製 mode 執行 als oct
Django建立一對多表結構
首先現在models.py中寫如下代碼:
from django.db import models# Create your models here.class Business(models.Model): caption = models.CharField(max_length=32)class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business",to_field="id")
這裡有幾個知識點:
1、b = models.ForeignKey(to="Business",to_field="id")
這裡的to參數是表示和那個表建立外鍵關係
to_field參數表示和表中那個欄位建立外鍵關係,如果不指定to_filed,預設則是與主鍵建立外鍵關係
2、同時關於ip地址格式在新版本中是:GenericIPAddressField
3、db_index=True設定索引
然後執行python manage.py makemigrations以及python manage.py migrate就可以在資料庫中建立出表結構
這裡有個問題需要注意:
如果在建立表結構後,你在Business表中添加了資料,並且這個時候你需要在Business中添加一列新的欄位的時候,如將建立Business表結構的類改成如下:
class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32)
這樣就比之前增加了一欄欄位code
如果不做其他設定,執行python manage.py makemigrations,這個時候會提示如下:
D:\python培訓\Django_zi_host>python manage.py makemigrations You are trying to add a non-nullable field ‘code‘ to business without a default; we can‘t do that (the database needs something to populate existing rows).Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.pySelect an option: 1Please enter the default value now, as valid PythonThe datetime and django.utils.timezone modules are available, so you can do e.g. timezone.nowType ‘exit‘ to exit this prompt>>> "sa"Migrations for ‘app01‘: app01\migrations\0002_business_code.py: - Add field code to businessD:\python培訓\Django_zi_host>python manage.py migrate
因為你的表中在添加code欄位之前已經有了資料,所以當添加新的欄位的時候你需要對之前已經有資料的資料行進行設定,這裡選擇1表示給之前已經有資料的行設定一個預設值,這裡我全部設定為sa
另外可以通過將類中code欄位的代碼進行修改如下:
code =models.CharField(max_length=32,null=True,default="SA")
這樣設定就表示code欄位可以為空白,並且給這個欄位設定了一個預設值為SA
擷取資料庫資料的三種方式
三種方式為:
models.Business.objects.all()
models.Business.objects.all().values("id","caption")
models.Business.objects.all().values_list("id","caption")
在views.py中寫如下代碼:
from django.shortcuts import renderfrom app01 import models# Create your views here.def business(request): v1 = models.Business.objects.all() v2 = models.Business.objects.all().values("id","caption") v3 = models.Business.objects.all().values_list("id","caption") return render(request,"business.html",{"v1":v1,"v2":v2,"v3":v3})
在urls.py中寫如下代碼:
urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^business$‘, views.business),]
url(r‘^business′,views.business),通過,可以防止如果還有:
url(r‘^business_add/‘, views.business),匹配不到,這通過符號,解決此類問題,如果沒有符號,就只會匹配上面的business,而不會匹配下面的bussiness_add
在business.html中寫如下代碼:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <h1>業務線列表(對象)</h1> {{ v1 }} <ul> {% for row in v1 %} <li>{{ row.id }}-{{ row.caption }}-{{ row.code }}</li> {% endfor %} </ul> <h1>業務線列表(字典)</h1> {{ v2 }} <ul> {% for row in v2 %} <li>{{ row.id }}-{{ row.caption }}</li> {% endfor %} </ul> <h1>業務線列表(元組)</h1> {{ v3 }} <ul> {% for row in v3 %} <li>{{ row.0}}-{{ row.1 }}</li> {% endfor %} </ul></body></html>
查看運行結果如下:
可以看出v1和v2以及v3其實都是QuerySet類型
區別在於:
v1中是QuerySet中存著每行資料的對象
v2中是QuerySet中存著資料對應的字典
v3中是QuerySet中存著資料對應的元組
這也是objects.all()、objects.all().values()、objects.all().values_list()的區別
一對多的跨表操作的三種方式
其實我們在建立ForeignKey的時候代碼中:
class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business",to_field="id")
其實這個b就是另外一張表的Business表的對象,當我們在views.py中寫host函數的時候,v1 = models.Host.objects.filter(nid__gt=0),這個時候我們可以知道v1是一個QuerySet,並且存著所有行資料的對象。
如果這個時候我們需要注意:如果我們通過for迴圈可以v1可以獲得每行資料任意列的資料,但是這裡host表中最後一列有點特殊
如果我們用如下代碼:
for row in v1: print(row.nid,row.hostname,row.port,row.ip,row.b_id,sep="\t")
我們知道資料庫中host表的最後一別是b_id,所以我們可以通過row.b_id獲得最後一列的值,我們也可以擷取row.b,這樣擷取的就是一個對象,而這個對象就是Business表中一行資料的對象,同樣的我們可以通過row.b.id、row.b.caption以及row.b.code,這就是跨表操作。
我們在views.py中添加如下代碼:
def host(request): v1 = models.Host.objects.filter(nid__gt=0) return render(request,"host.html",{"v1":v1})
host.html代碼如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <h1>業務線列表</h1> <table border="1"> <thead> <tr> <th>主機名稱</th> <th>IP</th> <th>連接埠</th> <th>業務線id</th> </tr> </thead> <tbody> {% for row in v1 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.ip }}</td> <td>{{ row.port }}</td> <td>{{ row.b.caption }}</td> </tr> {% endfor %} </tbody> </table></body></html>
這裡有個小知識需要注意:對於使用者id以及Bussines表的id、code我們並不需要在頁面上顯示,但是使用者id以及Bussines表的id是唯一的,後面可能需要擷取,所以將這兩個值作為了tr標籤的屬性,而code則不是必須的。最終頁面的效果如下:
同時這裡有一種跨表操作的方式:
當我們在host函數中:
v2 = models.Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b__caption")
這裡我們注意到跨表操作的時候用了b__caption,這裡其實無法用b.caption來跨表擷取資料,所以這是也是雙底線的一種用法
最終代碼如下:
host函數的代碼:
def host(request): v1 = models.Host.objects.filter(nid__gt=0) v2 = models.Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b__caption") v3 = models.Host.objects.filter(nid__gt=0).values_list("nid","hostname","b_id","b__caption") return render(request,"host.html",{"v1":v1,"v2":v2,"v3":v3})host.html代碼如下:<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <h1>主機列表(對象)</h1> {{ v1 }} <table border="1"> <thead> <tr> <th>主機名稱</th> <th>IP</th> <th>連接埠</th> <th>業務線id</th> </tr> </thead> <tbody> {% for row in v1 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.ip }}</td> <td>{{ row.port }}</td> <td>{{ row.b.caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>主機列表(字典)</h1> {{ v2 }} <table border="1"> <thead> <tr> <th>主機名稱</th> <th>業務線id</th> </tr> </thead> <tbody> {% for row in v2 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.b__caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>主機列表(元組)</h1> {{ v3 }} <table border="1"> <thead> <tr> <th>主機名稱</th> <th>業務線id</th> </tr> </thead> <tbody> {% for row in v3 %} <tr hid="{{ row.0 }}" bid="{{ row.2 }}"> <td>{{ row.1 }}</td> <td>{{ row.3 }}</td> </tr> {% endfor %} </tbody> </table></body></html>
效果如下:
這裡有個小知識點:
如果想要在表單的最左側有個序號列,方法如下:
在範本語言中只有有for迴圈,裡面就會有一個forloop
如果想要有一個需要直接添加forloop.counter,就可以了
這裡有幾個參數:
forloop.counter :表示從1開始計數
forloop.counter0:表示從0開始計數
forloop.first:如果是第一個則會會True,否則為False
forloop.last:如果是最後一個則會為True,否則為False
forloop.revcounter:將序號從大到小,最小為1
forloop.revcounter0:將序號從大到小,最小為0
forloop.parentloop:記錄外層迴圈的層數
初識Ajax
通過jQuery可以調用Ajax,方式如下:
$("#ajax_submit").click(function () { $.ajax({ url:"/test_ajax", type:"POST", data:{"hostname":$("#hostname").val(),"ip":$("#ip").val(),"port":$("#port").val(),"b_id":$("#sel").val()}, success: function(data) { var obj = JSON.parse(data) } }) })
關於ajax參數的解釋:
url:表示要傳遞資料的地址
type:表示傳遞的方式
data:表示要傳遞的資料
success:function{data}表示如果成功就會執行這個函數,這裡的data是伺服器返回的資料或者結果
這裡JSON.parse將字典進行還原序列化
一般情況,建議讓伺服器返回一個字典:
return HttpResponse(json.dumps(字典))
這裡有個知識點需要注意:
$.ajax({ data:$("#edit_form").serialize() })
data:$("#edit_form").serialize()這種方式就可以將form表單中的資料提交,而不用一個一個寫了
Django建立多對多
這裡有兩種方式:
自訂關係表
代碼例子如下:
class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32,null=True,default="SA")class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business",to_field="id")class Application(models.Model): name = models.CharField(max_length=32)class HostToApp(models.Model): hobj = models.ForeignKey(to="Host",to_field="nid") aobj = models.ForeignKey(to="Application",to_field="id")
自動建立關係表
代碼例子如下:
class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business",to_field="id")class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("Host")
如果是通過自動建立的則無法直接對第三張表進行操作,可以間接操作
例子如下:
obj = Application.objects.get(id=1)
obj.r.add(1) :表示建立Application表的id=1和host表中的id=1建立一個對應關係
obj.r.add(2) :表示建立Application表的id=1和host表中的id=1建立一個對應關係
obj.r.add(1,2,3,4):表示增加多個對應關係
obj.r.add(*[1,2,3,4]):表示增加多個對應關係
obj.r.remove(*[1,2,3,4]):表示刪除多個對應關係
obj.r.clear():這樣會刪除Application中id=1的對應關係都會給清空
obj.r.set([3,5,7]):這樣表示重設,將原有的關係刪除,然後只有和3,5,7的對應關係
obj.r.all():這裡獲得是所有相關的主機對象的“列表”即QuerySet
Django補充及初識Ajax