Django的数据库操作
Django创建一对多表结构
创建的项目的目录结构为
第一步是app01/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: 表示和那张表建立外键关系记住这个表名(表名对应的python中的class类,同时后面是一个字符串),这个to是必填的
to_field: 表示和建立外键关系中表的那个那个字段建立外键关系,这个可以不填,默认为外键的主键建立外键关系
2、db_index = True 这个表示的是设置成索引
3、models.GenericIPAddressField 这个表示约束属于字符串类型(ipv4和ipv6可选)
参数protocol可以是:both、ipv4、ipv6默认是both表示2种都支持
这个验证时,会根据你的设置看报不报错
上面设置好后我们需要在manage.py的同级目录下执行2个命令
python3 manage.py makemigrations
python3 manage.py migrate
这样我们就在数据库中创建了我们想要的表结构了。
这里需要注意的是当我们在上面的表中存储了数据,但是后来由于需求我们添加新的字段。
这样我们在执行数据创建的时候就会出现相关提示。
上面的修改为
class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32)
执行python3 manage.py makemigrations
上面的选项1)表示的是现在提供一个一次性的默认值,将已有行设置为该默认值
2)这个选项是说我们推出在设置里面自己这只默认值
如果选择2)我们代码为
class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32,default='aa')
这样我们才能更新数据库把现有的表的结构更新。
获取数据库的三种方式
def business(request): ret = models.Business.objects.all() print('ret',ret) print('ret',ret[0].id) ret1 = models.Business.objects.all().values() print('ret1',ret1) print('ret1',ret1[0]['id']) ret2 = models.Business.objects.all().values_list() print('ret2',ret2) print('ret2',ret2[0][0]) return HttpResponse('ok') #结果 ret <QuerySet [<Business: Business object>, <Business: Business object>, <Business: Business object>]> ret 1 ret1 <QuerySet [{'id': 1, 'caption': '运维部', 'code': 'aa'}, {'id': 2, 'caption': '开发部', 'code': 'aa'}, {'id': 3, 'caption': '销售部', 'code': 'aa'}]> ret1 1 ret2 <QuerySet [(1, '运维部', 'aa'), (2, '开发部', 'aa'), (3, '销售部', 'aa')]> ret2 1
从上面我们可以看出
models.Business.objects.all():这个查询出来的是QuerySet类似于列表的类型,但是列表里面的数据是一个对象。所以要取得相应的数据就要对对象进行操作
models.Business.objects.all().values():这个查询的也是QuerySet类似于列表的类型,但是列表中的数据是以字典的方式表现出来的。所以要取得相应的数据就要对字典进行操作
models.Business.objects.all().values_list():这个在里面表现的形式是以元组的方式展现出来的。所以要取得相应的数据就要对元组进行进行操作
下面是我们在网页中实现访问数据库数据并展示。
在app01.views.py中
from django.shortcuts import render,HttpResponse,redirect from app01 import models # Create your views here. def business(request): ret = models.Business.objects.all() ret1 = models.Business.objects.all().values() ret2 = models.Business.objects.all().values_list() return render(request,'business.html',{'ret':ret, 'ret1':ret1, 'ret2':ret2})
templates/business.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>业务线列表对象方式</h2> {{ ret }} <table border="1"> <thead> <tr> <th>id</th> <th>caption</th> <th>code</th> </tr> </thead> <tbody> {% for i in ret %} <tr> <td>{{ i.id }}</td> <td>{{ i.caption }}</td> <td>{{ i.code }}</td> </tr> {% endfor %} </tbody> </table> <h2>业务线列表字典方式</h2> {{ ret1 }} <table border="1"> <thead> <tr> <th>id</th> <th>caption</th> <th>code</th> </tr> </thead> <tbody> {% for i in ret1 %} <tr> <td>{{ i.id }}</td> <td>{{ i.caption }}</td> <td>{{ i.code }}</td> </tr> {% endfor %} </tbody> </table> <h2>业务线列表元组方式</h2> {{ ret2 }} <table border="1"> <thead> <tr> <th>id</th> <th>caption</th> <th>code</th> </tr> </thead> <tbody> {% for i in ret2 %} <tr> <td>{{ i.0 }}</td> <td>{{ i.1 }}</td> <td>{{ i.2 }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
上面是查询方式是查询表中的所有数据这里还有一些条件筛选。
models.Host.objects.filter(nid=2)
这个是查询Host表中nid为2的那条数据。返回的是一个QuerySet类似列表其中元素是对象
models.Host.objects.filter(nid__gt=2)
这个查询的是Host表中nid大于2的数据。返回的是一个QuerySet类似列表其中元素是对象
models.Host.objects.filter(nid__lt=2)
这个查询的是Host表中nid小于2的数据。返回的是一个QuerySet类似列表其中元素是对象
models.Hostobjects.filter(nid__gte=2)
这个查询的是Host表中nid大于等于2的数据。返回的是一个QuerySet类似列表其中元素是对象
models.Host.objects.filter(nid__lte=2)
这个查询的是Host表中nid小于等于2的数据。返回的是一个QuerySet类似列表其中元素是对象
上面这些查询在后面加上.values() 和.values_list()产生的变化分别和上面一样,类似列表中的元素分别是字典和元组。
一对多的表跨表查询的方式
在创建表结构的时候我们把两个表做了关联。
我们现在可以通过在写了外键的表中查询它所关联的那个表的数据。
from django.shortcuts import render,HttpResponse,redirect from app01 import models # Create your views here. def business(request): ret = models.Host.objects.filter(nid=2) for row in ret: print(type(row.b),row.b.caption) return HttpResponse('ok') #结果 <class 'app01.models.Business'> 开发部
从上面我们可以看到我们通过外键b能够查询到关联的那张表的数据。同时在表的结构中我们外键连接的另一张表的id
我们查询关联的id时,在表中边伟b_id。我们通过row.b.caption这个就数据跨表操作。
app01/views.py中的代码
from django.shortcuts import render,HttpResponse,redirect from app01 import models # Create your views here. def host(request): ret = models.Host.objects.all() return render(request, 'host.html',{'ret': ret})
templates/host.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>服务器信息</h2> <table border="1"> <thead> <tr> <th>主机名</th> <th>IP</th> <th>PORT</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for i in ret %} <tr> <td>{{ i.hostname }}</td> <td>{{ i.ip }}</td> <td>{{ i.port }}</td> <td>{{ i.b.caption }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
上面我没有把url对应关系写出来这里就不写了。
总结:
当我们实行查询得到的类似列表的QuerySet里面的元素是对象的时候,我们可以通过这个对象进行跨表查询。就像上面写的代码一样。
如果我们在后面加上values()、values_list(),这样的到的数据就不能够进行查询,不过我们可以通过在values(args),这个args表示的是我们查询的条件中在找到相应的关系
如:ret = models.Host.objects.filter(nid=2).values('nid','hostname','ip')
这个得到的结果只会显示后面的几个信息,相当进行了第二次筛选。如果想要这种方式进行跨表查询可以这样写
ret = models.Host.objects.filter(nid=2).values('nid','hostname','ip','b__caption'),这样就能够找通过外键b查询到关联的表的信息
上面b__caption记住进行跨表就需要外键加上双下划线再加上关联标的列名:外键__关联表列名。
这个后面的的values_list()和values的跨表操作是一样的。
追加信息:
如果我们想把后台获取的数据前面加一个序号:
html中可以写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>服务器信息</h2> <table border="1"> <thead> <tr> <th>序号</th> <th>主机名</th> <th>IP</th> <th>PORT</th> <th>业务线名称id</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for i in ret %} <tr> <td>{{ forloop.counter }}</td> <td>{{ i.hostname }}</td> <td>{{ i.ip }}</td> <td>{{ i.port }}</td> <td>{{ i.b_id}}</td> <td>{{ i.b.caption}}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
上面的forloop.counter我们还可以写一些其他的参数:
forloop.counter :表示从1开始计数
forloop.counter0:表示从0开始计数
forloop.first:如果是第一个则会会True,否则为False
forloop.last:如果是最后一个则会为True,否则为False
forloop.revcounter:将序号从大到小,最小为1
forloop.revcounter0:将序号从大到小,最小为0
forloop.parentloop:记录外层循环的层数
创建多对多的表结构
方式一、自定义关系表
from django.db import models # Create your models here. class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32,default='aa') 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')
上面我们可以通过 models.HostToApp.objects.create(hobi_id=1,aobj_id=2)来增加关系
方式二、自动创建关系表
from django.db import models # Create your models here. class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32,default='aa') class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) ip = models.GenericIPAddressField(protocol='ipv4',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 =models.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):表示增加多个对应关系 相当于创建 1-1 ,1-2,1-3,1-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类似列表(操作和列表一样)里面的元素是对象。
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提交form表单。
$.ajax({ data:$("#edit_form").serialize() })