标签:
一、今日内容
一、Django ORM连表操作
Q,F
二、Form表单验证
面向对象
正则
三、Session框架
面向对象
cookie
toanado扩展
二、Django ORM一对多数据创建和查找
1、数据创建
对于不是外键关联的表,可以直接创建
对于通过外键关联的表,可以通过两种方式创建数据:
方式a:通过id添加数据
def user_info(request): dic = {‘username‘:‘xx‘,‘age‘:88,‘user_type_id‘:1} #通过id添加数据 models.UserInfo.objects.create(**dic) result = models.UserInfo.objects.all() for item in result: print item.username,item.age,item.user_type.caption #对象访问属性
方式b:
dic = {‘username‘:‘alex‘,‘age‘:73,‘user_type‘:models.UserType.objects.get(id=1)} models.UserInfo.objects.create(**dic) result = models.UserInfo.objects.all() for item in result: print item.username,item.age,item.user_type.caption #对象访问属性
2、数据正向查找
对于不是外键关联的数据,直接通过如下方式查找
models.UserInfo.objects.filter(username=‘alex‘) #不是外键关联的数据
对于外键关联的数据,通过"__"双下划线如下的方式查找:
result = models.UserInfo.objects.filter(user_type__caption="CEO") #通过外键关联的数据的查找方式 for item in result: print item.username,item.age,item.user_type.caption return HttpResponse("OK")
3、数据反向查找
首先看一下表结构
from django.db import models class UserType(models.Model): caption = models.CharField(max_length=32) class UserInfo(models.Model): user_type = models.ForeignKey(UserType) #在创建数据的时候,需要下来创建选择用户类型,这种情况下需要是一对多 username = models.CharField(max_length=32) age = models.IntegerField()
可以看到UserType是通过外键被UserInfo表关联的表,所以,通过Usertype查找UserInfo表中的数据,称为反向查找
现在有如下需求:要求获取某个人的用户类型,并计算出该用户类型的用户的数量
分析:用户类型存在于UserType表中,但是用户名存在于UserInfo表中,可以直接通过正向查找,在Usertype表中获取指定用户的用户类型,因为用户名是跨表的,需要通过双下划线表示
通过在UserType表中创建用户类型的对象,利用_set反向关联UserInfo表,查找到对应用户的数量;
user_type_obj =models.UserType.objects.get(userinfo__username=‘alex‘) #对象(UserType) print user_type_obj.caption #实例 print user_type_obj.userinfo_set.all().count() return HttpResponse("OK")
在举一个栗子:
在前面的BBS项目中,如果要获取所有文章的点赞的个数,该如何实现呢?首先请看下面的表结构:
class MyUser(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) def __unicode__(self): return self.username class NEWs(models.Model): title = models.CharField(max_length=32) content = models.CharField(max_length=32) def __unicode__(self): return self.title class Favor(models.Model): user_obj = models.ForeignKey(MyUser) new_obj = models.ForeignKey(NEWs) def __unicode__(self): return "%s --> %s" %(self.user_obj.username,self.new_obj.title)
从上面的表结构可以看出,点赞的表Favor通过外键关联NEWs表和MyUser表,通过NEWs表,获取Favor表中的数据的个数,需要通过反向查找获取,如下:
new_list = models.NEWs.objects.all() #获取文章的实例 for item in new_list: print item.title print "#############" print item.content print item.favor_set.all().count() #反向查找
接下来需求改变,要求查找dali赞过的文章的个数;
分析:如果从NEWs表中开始查找,创建对象的时候需要通过双下划线跨表查询NEWs-->Favor-->MyUser,直到找到条件username=dali为止;
new_list = models.NEWs.objects.filter(favor__user_obj__username=‘dali‘) #filter返回的是列表,没有返回为[]
for item in new_list: print item.title print "#############" print item.content print item.favor_set.all().count()
注意:在创建对象的时候,如果是条件查询,需要使用到filter和get,注意区别是:get返回的是字典,无需循环,通过.直接获取需要的字段,并且如果返回值的不唯一或为空,就会报错;而对于filter返回的则是列表,返回值不唯一不会报错,并且如果值为空,返回[],注意获取字段的时候,需要循环; all()返回的也是列表;
4、好了,现在将数据查找的两种方式总结如下:
正向查找: filter(跨表) 对象__跨表的字段
line.对象.跨表的字段
反向查找:filter(跨表) 自动创建一个与表名相同的对象__跨表的字段
line.自动创建一个与表名相同的对象__set.filter()/all()[0:1]
二、Django ORM多对多数据创建和查找
1、正向添加数据
首先看一下表结构,对于多对多来讲,外键关联的字段HostAdmin/host可以放在任何一张表中,只不过这时候需要注意正向和反向即可
class Host(models.Model): hostname = models.CharField(max_length=32) port = models.IntegerField() class HostAdmin(models.Model): username = models.CharField(max_length=32) email = models.CharField(max_length=32) host=models.ManyToManyField(Host)
接下来创建数据
models.Host.objects.create(hostname=‘c1‘,port=80) models.Host.objects.create(hostname=‘c2‘,port=80) models.Host.objects.create(hostname=‘c3‘,port=80) models.HostAdmin.objects.create(username=‘alex‘,email=‘1@live.com‘) models.HostAdmin.objects.create(username=‘root‘,email=‘2@live.com‘) models.HostAdmin.objects.create(username=‘dali‘,email=‘3@live.com‘) models.HostAdmin.objects.create(username=‘haojie‘,email=‘4@live.com‘)
数据内容如下所示:
现在需要在关联的表host表中创建数据如下:
正向创建数据
admin_obj=models.HostAdmin.objects.get(username=‘dali‘) #创建username的对象 host_list=models.Host.objects.filter(id__lt=3) #创建主机id小于3的对象 admin_obj.host.add(*host_list) #添加数据 return HttpResponse("OK")
2、反向数据添加
host_obj =models.Host.objects.get(id=3) admin_list = models.HostAdmin.objects.filter(id__gt=1) #id值大于1 host_obj.hostadmin_set.add(*admin_list) #反向数据添加
总结:正向数据添加还是反向数据添加,取决于多对多的关联的字段存在于哪个表中;相同点是:都是一张表中的一个固定的值对另外一张表的多个值;
3、Django 多对多自定义第三张关系表
如下三张表,对于第三张关系表,第一张表和第二张表是第三张表的外键,其表中的字段全部通过外键关联其他的表,那么可不可以让第三张表中存在其他的字段呢?答案是可以的
看下面:Django 多对多ORM创建第三张自定义的关系表,通过through参数实现;
class Host1(models.Model): hostname = models.CharField(max_length=32) port = models.IntegerField() class HostAdmin1(models.Model): username = models.CharField(max_length=32) email = models.CharField(max_length=32) host=models.ManyToManyField(Host1,through=‘HostRelation‘) class HostRelation(models.Model): c1=models.ForeignKey(Host1) C2=models.ForeignKey(HostAdmin1)
#可以在下面继续增加其他的字段,如果需要的话
那问题来了?自定义的第三张表有了,数据如何写入呢?
事实上,此时在第三张表中写入数据,是写入的id的值,有两种方式:通过查询对象写入和直接写入,看下面
#通过查询对象写入,需要查询之后执行数据库操作
models.HostRelation.objects.create( c1=models.Host1.objects.get(id=1), C2=models.HostAdmin1.objects.get(id=2) )
#直接写入,无需查询,推荐的方式;
models.HostRelation.objects.create( #0次数据库查询,一次数据库插入 c1_id=2, C2_id=1, )
4、Django ORM多对多数据查询的两种方式
方式1:
#正向查 admin_obj =models.HostAdmin.objects.get(id=1) admin_obj.host.all() #反向查 host_obj =models.Host.objects.get(id=1) host_obj.hostadmin_set.all()
方式2:通过自定义的第三张表查询(推荐)
relation_list = models.HostRelation.objects.all() for item in relation_list: print item.c1.hostname print item.C2.username relation_list1 = models.HostRelation.objects.filter(C2__username=‘alex‘) for item in relation_list1: print item.c1.hostname print item.C2.username
比较:第二种方式可以查询所有的数据,并且操作数据库的次数少,,并且便于扩展(添加新的字段)推荐使用;
标签:
原文地址:http://www.cnblogs.com/cqq-20151202/p/5744824.html