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. VS2012下X64平台嵌入汇编程序

    VS2012在win32平台编译的时候可以很好的支持汇编语言的嵌入.建立一个控制台应用程序,选择空项目.项目建立好之后添加一个.cpp文件.在cpp文件中写入如下代码: #include <io ...

  2. python 函数传递方式

    在python中方法传递的参数到底是值传递还是引用传递? 1. 首先需要知道python中变量的类型:Python的变量分为可变变量和不可变变量. 针对于不可变的类型比如string int def ...

  3. Linux Tomcat 开机自启动的方法

    修改Tomcat/bin/startup.sh 为: export JAVA_HOME=/usr/java/j2sdk1.4.2_08 export CLASSPATH=$CLASSPATH:$JAV ...

  4. Android入门(一):Android发展史

    Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发.尚未有统一中文名称,中国大陆地区较多人使用“安卓” ...

  5. Using MySQL Connector .NET 6.6.4 with Entity Framework 5

    I had been waiting for the latest MySQL connector for .NET to come out so I can move on to the new a ...

  6. PHP图片裁剪类

    <?php class ImageTool { //以宽为标准,如果小于宽,则不剪裁 public static function thumb_img_by_width($src_path, $ ...

  7. 2016 CCPC长春重现赛

    1.2016中国大学生程序设计竞赛(长春)-重现赛 2.总结:会做的太少,应变能力也不行,或者说猜题目的能力不行 02  水 04  HDU 5914  Triangle 1.题意:1~n,n个数,问 ...

  8. ARM大学计划全球经理到访华清远见,深入交流教育合作

    来源:华清远见嵌入式学院 10月20日,ARM大学计划全球经理Khaled Benkrid,高级内容主编洪川博士在ARM大学计划亚太经理陈炜博士的陪同下到访华清远见,就最新嵌入式技术.ARM处理器在教 ...

  9. thinkphp pathinfo nginx 无法加载模块:Index

    thinkphp 报了 无法加载模块:Index 错误位置 FILE: /var/multrix/wxactivity_archive/ThinkPHP/Library/Think/Dispatche ...

  10. 下载更新文件后,调用安装器自动安装apk文件

    在更新操作时,下载新apk之后,往往需要自动安装新apk,用以下代码即可安装下载在本地的apk文件(apkFile) Intent intent = new Intent(); intent.setA ...