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="">
<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="">
<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="">
<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="">
<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的更多相关文章

  1. Django(四) ORM 外键操作及初识Ajax

    一.内容回顾 1.Django请求的生命周期: ​ 路由系统 -> 视图函数(获取模板+数据 -> 渲染) -> 字符串返回给用户 2.路由系统: /index/ #-> 函数 ...

  2. {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)

    Django基础七之Ajax 本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 一 Ajax简介 ...

  3. {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)

    {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)   Django基础七之 ...

  4. day 72 Django基础七之Ajax

    Django基础七之Ajax   本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 六 同源策略与 ...

  5. day 60 Django基础七之Ajax

      Django基础七之Ajax   本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 六 同源策 ...

  6. Django框架 之 基于Ajax中csrf跨站请求伪造

    Django框架 之 基于Ajax中csrf跨站请求伪造 ajax中csrf跨站请求伪造 方式一 1 2 3 $.ajaxSetup({     data: {csrfmiddlewaretoken: ...

  7. django补充CBV和FBV模式

    django补充CBV和FBV模式FBV模式---函数:经常用的方式CBV模式---类CBV中url连接时函数名后面要接.as_view()class index(views.View): @... ...

  8. Django基础五之Ajax

    Django基础五之Ajax 目录 Django基础五之Ajax 1. Ajax介绍 2. Ajax前后端传值 2.1 方法一HttpResponse直接返回 2.2 方法二使用Json格式返回 2. ...

  9. python django初识ajax

    什么是json json是轻量级文本数据交互格式 json独立语言 符合的json对象 ["one", "two", "three"] { ...

随机推荐

  1. 吃透Javascript数组操作的正确姿势—再读《Js高程》

    Javascript中关于数组对象的操作方法比较多也比较杂,正好再次捡起<Javascript高级程序设计>来读,把它们一一总结梳理了一下: 方法类别 方法名称 方法描述 参数 返回值 备 ...

  2. 如何利用 JConsole观察分析Java程序的运行,进行排错调优

    原文链接:http://jiajun.iteye.com/blog/810150 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能 ...

  3. ubuntu更新软件源

    更新源方法: 1. 打开终端.单击主菜单中的“应用程序 - 附件 - 终端”. 2. 修改更新服务器列表.请在终端中执行下面的两条命令: sudo cp /etc/apt/sources.list / ...

  4. sql Lloader

    create table ban_ji(id integer,ban_ji varchar2(25))insert into ban_ji values(1,'1-(1)');insert into ...

  5. 一把鼻涕一把泪 搭建公网ftp服务器

    至于为什么要搭建公网ftp服务器,就当我心血来潮吧. ftp开源工具很多,咱用的是filezilla服务器.后来为了方便搭建web服务器,就改成了集成工具xampp.客户端工具也是filezilla ...

  6. 探索摸寻之XCode 快捷键

    注释/反注释 Command+/ 模拟器没有Home键 在模拟器的应用界面 Command+Shift+h 返回上一级 (1920,24寸显示器,因此不是分辨率问题)

  7. C# 与 C++ 数据类型比较及结构体转换

    引自:http://www.blogjava.net/heting/archive/2010/03/20/315998.html   C++            C# =============== ...

  8. [NOIP2011]Mayan游戏 题解

    题目大意: 有一个5*7的方格,上面有几种颜色的方块,如果在一横行或者竖列上有连续三个或者三个以上相同颜色的方块,则它们将立即被消除,方块消除之后,消除位置之上的方块将掉落.每步移动可以且仅可以沿横向 ...

  9. ASP.NET页面的字符编码设置

    在用ASP.NET写网上支付的接口程序时,遇到一个奇怪问题,通过表单提交过去的中文全是乱码,英文正常.而用asp程序进行测试,可以正常提交中文,asp页面中有这样的HTML代码: <meta h ...

  10. About_Web

    成功网站的三要诀:内容.设计.营销 内容为王: 高质量的内容会促使网站走向成功.首先,用户有需求,他们需要被感动,被娱乐,被有料的内容和产品所吸引.漂亮的背景和亮骚的特效可能会有所助益,但终究只是辅助 ...