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. Build2016上值得一看的大数据相关Session

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:Build2016开完很久了,现在才来回顾下,就说说那些和大数据相关的Session, ...

  2. jquery实现页面交互的几个小例子

    翻看了以前留下的笔记,发现自己竟然做过这么多的页面交互效果,没有使用原生js,全是通过jquery实现的,于是把他们整理下来,附上表现效果图及源代码 1 业务应用:授权商品组和删除商品组 本质:复选框 ...

  3. PHP 检查并创建多级目录

    <?php //检查并创建多级目录    function checkDir($path){        $pathArray = explode('/',$path);        $no ...

  4. Python爬虫学习(5): 简单的爬取

    学习了urllib,urlib2以及正则表达式之后就可以做一些简单的抓取以及处理工作.为了抓取方便,这里选择糗事百科的网页作为抓取对象. 1. 获取数据: In [293]: url = " ...

  5. compass color 颜色 对比色[Sass和compass学习笔记]

    最基本的api 是对比色,对与我这种菜鸟来说,没有什么比在一个背景色下 用什么颜色的文字坑蛋疼的事情了,这个工具可以帮助大家很好解决这个问题 api 地址 http://compass-style.o ...

  6. crawler4j 学习

    crawler4j 学习(一) crawler4j是一个轻量级多线程网络爬虫,开发者可以调用相应的接口在短时间内创建一个多线程网络爬虫. 前期准备 使用maven 为了使用最近版本的crawler4j ...

  7. java分享第八天-01(线程)

     创建线程:1 可以实现Runnable接口.2 可以扩展Thread类本身. 通过实现Runnable创建线程:创建一个线程,最简单的方法是创建一个实现Runnable接口的类.为了实现Runnab ...

  8. Sublime Text 2配置文件详解

    Sublime Text 2是那种让人会一眼就爱上的编辑器,不仅GUI让人眼前一亮,功能更是没的说,拓展性目前来说也完全够用了,网上介绍软件的文章和推荐插件的文章也不少,而且很不错,大家可以去找找自己 ...

  9. tachyon of zybo cluster

    把Tachyon层加入spark和hadoop之间,以加速集群 官网:http://tachyon-project.org/ github:https://github.com/amplab/tach ...

  10. 四则运算之Right-BICEP测试

    Right-结果是否正确? 正确 B-是否所有的边界条件都是正确的? Conformance(一致性):值是否和预期的一致  是一致的 Ordering(顺序性):值是否如应该的那样 是 是有序或者无 ...