Django中的ORM进阶操作

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

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

铭记于心的两条:

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

一、一对多

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

# --*-- coding:utf-8 -*-
from django.db import modelsclass 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()

  

1、添加数据:

  传id的方式:(字典的形式传参)

user_dict = {"username": "chenchao", "age": "18", "user_type_id": 1}models.UserInfo.objects.create(**user_dict)

  

  传对象的方式:

user_type_obj = models.UserType.objects.get(id=1)   #先获取外键表中的数据对象
user_dict = {"username": "chenchao", "age": "18", "user_type": user_type_obj}        #将对象传入字典models.UserInfo.objects.create(**user_dict)

讲解:在我们写的models类时,外键的字段是”user_type",而django在数据库中保存字段时默认会在后面加“_id”,所以可以直接通过传id的方式。

      而在表中的外键字段“user_type”又代表的是字典表中的一行数据对象。于是同样可以传对象的方式来传参。

2、删除数据

3、修改数据  (这两个操作与上面的添加用法基本一致)

4、查找数据

   正向查找:(基于存在外键值表的查找为正向)

models.UserInfo.objects.filter(user_type__caption= "CEO")   #查找用户类型为CEO的所有用户, 双下划线”__“

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

  • 我们创建的外键表有两个字段,id、caption。但Django默认在外键的表里还会埋藏一个字段为userinfo。可以get一个表中不存在的值,通过返回的报错黄页里面可以查看到。
  • 通过models获取的值都是Qureyset。只要是这个类型就可以用.filter .all .count方法
  • 我们知道user_type_obj获取的是外键表中的一行数据对象。
    • user_type_obj.id  代表一个数据
    • user_type_obj.caption  代表一个数据
    • user_type_obj.userinfo_set  特殊,代表的是一种能力。这个能力就可以获取到这个用户类型下的所有用户或者某几个用户
    • request.user  代指的是django自带的auth表里的一行数据,与userinfo做了一个OneToOne,与正向查询是一样的。所以也可以用request.user.userinfo.filter....

举例:获取某个人是什么用户类型?当前用户类型下有多少人?

user_type_obj = models.UserType.objects.get(userinfo__username= "chenchao")  #通过外键表来找到隐藏的userinfo字段下的username
user_type_obj.caption  # 获取用户chenchao的用户类型
user_type_obj.userinfo_set.all().count()  #获取此类型下的所有用户个数

点赞的例子:

首先设计一下数据库表结构,使点赞的一张表与用户和文章建立外键关系

class MyUser(models.Model):username = models.CharField(max_length=32)password = models.CharField(max_length=64)def __unicode__(self):return self.usernameclass News(models.Model):title = models.CharField(max_length=32)content = models.CharField(max_length=32)def __unicode__(self):return self.titleclass 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)

点赞表结构

通过反向来操作点赞表,获取点赞的数量

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.titleprint items.contentprint 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、增加数据

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

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的字段将主机与用户的对象添加到第三张表中

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

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、查找数据

  正向查找:(基于存在外键值的表

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

  反向查找:(基于不存在外键值的表

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

自定义Django的多对多的第三张表:

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

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

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.usernameprint 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     #先要导入Fmodels.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连接

 

             

转载于:https://www.cnblogs.com/chenchao1990/p/5386510.html

Django中的ORM进阶操作相关推荐

  1. Django中的ORM操作之高级查询aggregate和annotate方法

    Django中的ORM操作之高级查询aggregate和annotate方法 aggregate()方法详解 annotate()方法详解 aggregate和annotate应用场景 Django中 ...

  2. Python全栈:Django中的ORM模型

    文章目录 1 Django中的ORM模型介绍及配置 2 Django中的ORM模型常见字段类型 CharField DateTimeField 模型的创建 3 Django中的ORM模型同步 migr ...

  3. web.py中实现类似Django中的ORM的查询效果

    Django中的对象查询 Django框架自带了ORM,实现了一些比较强大而且方便的查询功能,这些功能和表无关.比如下面这个例子: class Question(models.Model):quest ...

  4. Django中Model模块的操作-创建各种表结构(上)

    Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLd ...

  5. [django框架2]ORM进阶知识

    经过上周的django学习与项目实战,想必对其也有了足够的了解. django基础知识 项目实战 本次django进阶知识重要围绕数据库管理操作为主,同时讲述了部分关于组件中间件的内容,希望有所帮助. ...

  6. Django中的ORM模型

    一.Djang的ORM框架 (一)ORM 1.O(objects):类和对象. 2.R(Relation):关系,关系数据库中的表格. 3.M(Mapping):映射. (二)ORM框架功能 1.建立 ...

  7. Django笔记:ORM模型

    Django中操作数据库的方式有两种,一种是使用ORM模型,另一种是直接执行SQL,推荐使用ORM模型的方式来管理数据库,因为当需要执行的数据库操作过多时,第二种方式产生的SQL会非常难于管理和维护, ...

  8. Django中的Object Relational Mapping(ORM)

    ORM 介绍 ORM 概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用 ...

  9. Django中ORM操作

    一.ORM简介 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. ​ 简单的说,ORM是通过使用描述对象 ...

最新文章

  1. leetcode155. 最小栈
  2. jQuery学习笔记——jQuery基础核心
  3. 类 workbooks 的 open 方法无效_第十九章 Cach 命令大全 OPEN 命令
  4. 数据库系统工程师5天修炼_程序员逆袭之路,5年IT人生从电脑装机到技术大神,人生不认输...
  5. 终于有人对语音技术来了次彻头彻尾的批判!
  6. Oracle 11.2.0.2 Patch 说明
  7. Ubuntu18.04安装CAJViewer
  8. MySQL学习笔记10:MySQL图形化管理工具 navicat 和 Workbench
  9. SSH java 面试题
  10. 深圳市工业和信息化局关于征集创新产品的通知
  11. 隐藏桌面和控制面板网络连接
  12. java信用卡卡号算法,java实现主要信息的加密解密(模拟信用卡号的保存)
  13. Could not fetch URL https://pypi.org/simple/pip/: There was a problem confirming
  14. 北大扫地僧“火”了!手提馒头矿泉水的他,是博士毕业1年就成北大助理教授的90后!...
  15. 学习了网络营销信息传递原理,如何应用于就业求职?
  16. 林阳斌集美大学计算机学院,传一科技集美大学16级计算机认知实习圆满结束
  17. SCI 投稿全过程信件模板
  18. 计算机建筑绘图第二阶段在线作业,中石油华东《计算机建筑绘图》2018年秋学期在线作业资料...
  19. 如何防御DDoS CC攻击
  20. Jaspersoft Studio软件使用

热门文章

  1. Logistic逻辑回归用初等数学解读逻辑回归
  2. php再次确认密码,Laravel6.2中用于用户登录的新密码确认流程详解
  3. 30岁的你收入是多少?用数据可视化,看看大家的30岁工资真相
  4. 永擎服务器主板稳定性,主板看不停 Computex2015华擎展台一览
  5. 查看sql_一键查看Oracle数据库当前SQL_WORKAREA_ACTIVE的相关操作
  6. windows加密和linux加密_Windows系统自带的BitLocker加密方法
  7. 考虑题4所示的日志记录_基于Log4Net实现日志信息双向存储
  8. linux串口环形缓冲区,能不能讲解下串口环形缓冲区的概念?
  9. selenium python怎么断言_如何为python / selenium中的特定元素断言文本?
  10. 递归求解全排列问题以及八皇后问题