1. 程式人生 > >Django補充及初識Ajax

Django補充及初識Ajax

gen 以及 test model file ger key 字段 render

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.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type ‘exit‘ to exit this prompt
>>> "sa"
Migrations for ‘app01‘:
  app01\migrations\0002_business_code.py:
    - Add field code to business

D:\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 render
from 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