您的位置:首页 > 编程语言 > Go语言

Django中的ORM进阶操作

2016-04-13 11:41 260 查看

Django中的ORM进阶操作

Django中是通过ORM来操作数据库的,通过ORM可以很easy的实现与数据库的交互。但是仍然有几种操作是非常绕也特别容易混淆的。于是,针对这一块,来一个分类总结吧。

对于ORM对数据库的基本操作前面model里已经有了介绍,这里专门针对ORM的一对多、多对多、正向、反向等操作来讲解用法和注意事项。

铭记于心的两条:

在联表操作过滤查找数据时用双下划线 "__"

在取数据时用点 "."

一、一对多

  首先来设计两张简单的表格,并在其中一张表中设置一个另外一张表的外键值  

def FoverNum(request):

# 获取所有文章的标题 内容和点赞数
# n_num = models.News.objects.all()   # 获取所有新闻表的数据对象
# for item in n_num:
#     print items.title
#     print items.content
#     print item.favor_set.all().count()

# 获取chenchao点过赞的所有的文章
all_new = models.News.objects.filter(favor__user_obj__username="chenchao")

for items in all_new:
print items.title
print items.content
print items.favor_set.all().count()

return HttpResponse("Nothing")


操作表

二、多对多

首先设计好多对多的表结构:





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就可以创建,而第三张表django自动帮我们创建完成。我们主要针对第三张表,对其操作增删改查。

1、增加数据

   正向添加([b]基于存在外键值表的查找为正向): add[/b]

user_obj = models.HostAdmin.objects.get(username="chenchao")   # 获取某个用户的数据对象
host_obj = models.Host.objects.filter(id__lt=3)   # 获取id小于3的主机数据对象
user_obj.host.add(*host_obj)   # 通过用户对象下的ManyToMany的字段将主机与用户的对象添加到第三张表中


  反向添加:([b]基于不存在外键值表的查找为反向查找,前提是两张表已经建立了关系)[/b]

host_obj = models.Host.objects.get(id=1)   # 1、获取主机的数据对象
user_obj = models.HostAdmin.objects.filter(id__gt=1)   # 2、获取用户id大于1的数据对象
host_obj.hostadmin_set.add(*user_obj)      # 3、通过隐藏的外键字段hostadmin将主机对象与用户对象添加到第三张表


2、查找数据

  正向查找:([b][b]基于存在外键值的表[/b])[/b]

user_obj = models.HostAdmin.objects.get(id=1)  # 获取用户的数据对象
print user_obj.host.all().count()              # 基于用户对象,通过外键字段来查找第三张表中的个数


  反向查找:([b][b]基于不存在外键值的表[/b])[/b]

host_obj = models.Host.objects.get(id=1)       # 获取主机的数据对象
print host_obj.hostadmin_set.all().count()     # 基于主机对象,通过隐藏的hostadmin_set字段来查找第三张中的数据


自定义[b]Django的多对多的第三张表:[/b]

  django除了能自动创建多对多的第三张表,同样也可以自定义创建多对多的第三张表,而且操作和管理扩展等难易程度要比自动创建的好许多。所以,在之后的models表结构中,推荐使用自定义的方式。

仅仅在创建时添加一个字段即可:through='HostRelation' 。 [b]HostRelation是我们自定义的第三张表名。[/b]

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)


1、创建数据

操作自定义创建的多对多关系表的两种方式:

def ManytoM(request):

models.HostRelation.objects.create(    # 传对象的方式向第三张表中添加数据,笨法
c1=models.Host1.objects.get(id=1),
c2=models.HostAdmin1.objects.get(id=2)
)
models.HostRelation.objects.create(c1_id=2, c2_id=1,)  # 传id的方式向第三张表中添加数据,easy idea

return HttpResponse("add_many to many OK")


2、查找数据

relation_list = models.HostRelation.objects.all()  # 直接通过自定义的第三张表来查找数据

for item in relation_list:
print item.c1.hostname    # 通过点”.“ 来获取数据
print item.c2.username

print models.HostRelation.objects.filter(c2__username="chenchao")   # 通过双下划线”__“来查找数据


  

三、select_related

select_related:用来优化数据库查询的操作,可以没有,但优化的不够彻底。

用于在foreignkey查询的时候使用。可以通过query来查看一下django执行的sql语句。

ret1 = models.UserInfo.objects.all()
ret2 = models.UserInfo.objects.all().select_related()
print ret1.query
print ret2.query            # 查看django执行的sql语句


ret1:

SELECT
"App01_userinfo"."id",
"App01_userinfo"."user_type_id",
"App01_userinfo"."username",
"App01_userinfo"."age"

FROM "App01_userinfo"

ret2:

SELECT
"App01_userinfo"."id",
"App01_userinfo"."user_type_id",
"App01_userinfo"."username",
"App01_userinfo"."age",
"App01_usertype"."id",
"App01_usertype"."caption"
FROM
"App01_userinfo" INNER JOIN "App01_usertype"

ON
("App01_userinfo"."user_type_id" = "App01_usertype"."id")


通过sql语句我们可以清晰地看到select_related不仅把当前表的内容查找出来,而且还把外键的表里的数据也查了出来。如果我们按ret1的方式,需要在多执行一次sql的查找操作。而ret2只需要执行一次。

四、Django神奇的F

如果一张表中的数字列需要增加,那么F是最神奇的操作。

例如我们需要把user_info表里的所有age加1:

from django.db.models import F     #先要导入F

models.user_info.objects.all().update(age=F('age')+1)   #执行+1


五、Django更神奇的Q

当做复杂的搜索查找条件时,django的Q可以提供非常便利的方法。

在设计搜索条件时,相同的字段为或操作(OR),不同的字段之间是且操作(AND)

from django.db.models import Q    # 导入Q
con = Q()   # 创建Q对象

q1 = Q()
q1.connector = 'OR'      # q1的元素为OR或的关系
q1.children.append(('id', 1))
q1.children.append(('id', 10))
q1.children.append(('id', 9))

q2 = Q()
q2.connector = 'OR'      # q2的元素为OR或的关系
q2.children.append(('c1', 1))
q2.children.append(('c1', 10))
q2.children.append(('c1', 9))

con.add(q1, 'AND')      # 将q1添加到con对象中,与其他的Q为且的关系
con.add(q2, 'AND')

models.Tb1.objects.filter(con)   #将总的Q对象添加到model的查找条件中


提示:

1、之前所有的方法 如__gt,__lt,__contains. 双下划线联表查询等等都可以继续使用
2、append添加的是一个元组
3、最外层是用AND连接

             
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: