概念说明

  • ORM:关系对象映射的全称是 Object Relational Mapping, 简称ORM
  • SQLAlchemy: 是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

ORM方法论基于三个核心原则:

简单:以最基本的形式建模数据。
传达性:数据库结构被任何人都能理解的语言文档化。
精确性:基于数据模型创建正确标准化了的结构。

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

对于ORM框架里:

我们写的类表示数据库的表
如果根据这个类创建的对象是数据库表里的一行数据

理解

首先在理解ORM的时候,我们可以把一对多、多对多 分为正向和反向!

什么是正向呢?看下面的代码!

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()

ForeignKey 在UserInfo表里,如果根据UserInfo去操作就是正向,

因为 ForeignKey 不在UserType里,如果根据UserType去操作反向。

下面我们分别说明 一对多、多对多。

环境

创建一个Project并且创建一个叫做api的APP,数据模型代码如上;

安装一个插件 django-extensions ,这个插件可查看执行sql

pip install django-extensions

INSTALLED_APPS = (
...
'api',
'django_extensions',
)

生成数据库和表结构,这里我们用django默认的数据库sqlite3,如下是建表:

python manage.py makemigrations api
python manage.py migrate

ORM一对多

什么时候使用一对多?

在设计表结构的时候什么时候使用一对多呢?比如我在创建用户的时候有个菜单让我们选择用户类型的时候,使用一对多!

一对多正向反向

首先怎们看下UserType这个表,他没有关联其他表我们在添加的时候没有什么特殊直接添加就行:

进入django shell命令行

python manage.py shell_plus --print-sql
>>> from api.models import *

我们依次添加:CEO、CFO、COO 3个用户组

>>> UserType.objects.create(caption='CFO')
BEGIN
Execution time: 0.000000s [Database: default]
INSERT INTO "api_usertype" ("caption") VALUES ('CFO')
Execution time: 0.001000s [Database: default]
<UserType: UserType object>
id caption
1 CEO
2 CFO
3 COO

正向:增

在看下UserType这个表,默认他在创建的时候回有4列,ID、username、user_type_id、age

| id | username | user_type_id | age |

所以我们在创建UserType数据的时候有两种方法:第一种方法是直接根据这个字段进行添加数据!给user_type 加 '_id'

>>> UserInfo.objects.create(username='one',age=18,user_type_id=1)
INSERT INTO "api_userinfo" ("user_type_id", "username", "age") VALUES (1, 'one', 18)

或者通过对象添加

>>> usertype = UserType.objects.get(id=2)
SELECT "api_usertype"."id", "api_usertype"."caption" FROM "api_usertype" WHERE "api_usertype"."id" = 2
>>> UserInfo.objects.create(username='two',age=23,user_type=usertype)
INSERT INTO "api_userinfo" ("user_type_id", "username", "age") VALUES (2, 'two', 23)

添加数据后 userinfo表如下:

id username age user_type_id
1 one 18 1
2 two 23 2
3 three 78 1

正向:查

  • 查询所有用户type为CEO的用户名字
>>> allceo = UserInfo.objects.filter(user_type__caption='CEO')
>>> for i in allceo:
... print i.username
one
three
  • 正向查询用户为one的所有身份,user_type
>>> user = UserInfo.objects.filter(username='one')
... print i.user_type.caption
SELECT "api_usertype"."id", "api_usertype"."caption" FROM "api_usertype" WHERE "api_usertype"."id" = 1 CEO

反向:查

我们知道 UserType 表与 UserInfo 表是通过 UserInfo 里面的 user_type_id 外键来建立联系的,做正向查询的时候通过 user_type_id 外这个外键就可以查询到 UserType 表里的数据。其实在这两个表创建联系的时候,Django在 UserType 表里
也创建了一个隐藏的 userinfo 字段来与 UserInfo 表进行关联。那么如果我们要在 UserType 表里查看 one 所对应的所有 usertype 的话,就可以利用 UserType 表里的隐藏字段来关联用户名称。代码如下:

  • 反向查询用户为one的所有身份,user_type
>>> user = UserType.objects.filter(userinfo__username='one')
>>> for i in user:
... print i.caption
SELECT "api_usertype"."id", "api_usertype"."caption" FROM "api_usertype" INNER JOIN "api_userinfo" ON ("api_usertype"."id" = "api_userinfo"."user_type_id") WHERE "api_userinfo"."username" = 'one' CEO

可以看到与上面正向查询的方式是不一样的;
上面代码中的user还有如下几种方法:

>>> for obj in user:
... print obj.caption
... print obj.id
... print obj.userinfo_set #理解为一种能力,可以获取所有当前这个用户类型的用户/或者这个用户类型的多个用户
... print obj.userinfo_set.all() #获取所有用户类型为COO的用户
... print obj.userinfo_set.filter(username='one') #获取用户类型为COO的并且用户为one的用户

这里 userinfo_set 它相当于 UserInfo.objects.filter(user_type=obj)

一对多的简单总结

1、查询数据 也就是通过models.xxx.objects.filter()里填写查询条件的时候。这个时候获取的结果是一组数据行对象,不是具体的某个数据。跨表查询用到 对象名称__字段名(双下划线)
2、获取数据 也是具体到要获取某个字段的数据的时候。跨表操作通过'.'来连接各个表
3、反向查找的时候,查找的的表里会创建一个隐藏掉字段,这个字段名就是与创建外键的表同名
4、反向获取数据的时候,通过xxx_set.all()才能获取到 xxx所有被匹配到的对象
5、尽量用正向操作,反向的看着就麻烦。

orm常用操作

# 增
models.Tb1.objects.create(c1='xx', c2='oo') #增加一条数据,可以接受字典类型数据 **kwargs
obj = models.Tb1(c1='xx', c2='oo')
obj.save()
#
# 查
models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.all() # 获取全部
models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
#
# 删
models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
#

models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs
obj = models.Tb1.objects.get(id=1) # 修改单条数据
obj.c1 = '111'
obj.save() #
# 获取个数
models.Tb1.objects.filter(name='seven').count()
#
# 大于,小于
models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值
models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
#
# in
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
#
contains
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.exclude(name__icontains="ven")
#
# range
models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
#
# 其他类似
startswith,istartswith, endswith, iendswith,
#
# order by
models.Tb1.objects.filter(name='seven').order_by('id') # asc
models.Tb1.objects.filter(name='seven').order_by('-id') # desc
#
# limit 、offset
models.Tb1.objects.all()[10:20]
#
# group by
from django.db.models import Count, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

作者:撸大师
链接:https://www.jianshu.com/p/b9c85da0b159
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Django下orm学习 一对多的更多相关文章

  1. Python学习---django之ORM语法[对象关系映射]180124

    ORM语法[对象关系映射] ORM: 用面向对象的方式去操作数据库的创建表以及增删改查等操作. 优点:1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句.快速开发. 2 ...

  2. Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终端打印SQL语句,脚本调试)

    Django---Django的ORM的一对多操作(外键操作),ORM的多对多操作(关系管理对象),ORM的分组聚合,ORM的F字段查询和Q字段条件查询,Django的事务操作,额外(Django的终 ...

  3. Django模型层ORM学习笔记

    一. 铺垫 1. 连接Django自带数据库sqlite3 之前提到过Django自带一个叫做sqlite3的小型数据库,当我们做本地测试时,可以直接在sqlite3上测试.不过该数据库是小型的,在有 ...

  4. Python学习---django下的cookie操作 180201

    什么是Cookies 什么是Cookies cookies设置的原因: 1. http请求的无记忆性: 2.加快访问速度  3. 减少服务器压力 cookies特点: cookies保存在客户端浏览器 ...

  5. 数据库开发-Django ORM的一对多查询

    数据库开发-Django ORM的一对多查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.联合主键问题 CREATE TABLE `employees` ( `emp_no` ...

  6. Django之ORM操作

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

  7. 九、Django之ORM

    一.ORM概述 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 到目前为止,当我们的程序涉及到数据库相关操作时,一般操作流 ...

  8. Django 的ORM 表间操作

    Django之ORM表间操作   之前完成了简单的数据库数据增加操作.这次学习更多的表间操作. 单表操作 增加 方式一 b = Book(title="Python基础", pub ...

  9. Django的ORM实现数据库事务操作

    在Django中实现数据库的事务操作 在学习MySQL数据库时,MySQL数据库是支持原子操作的. 什么是数据库的原子操作呢??打个比方,一个消费者在一个商户里刷信用卡消费. 交易正常时,银行在消费者 ...

随机推荐

  1. luogu4366 [Code+#4]最短路[优化建边最短路]

    显然这里的$n^2$级别的边数不能全建出来,于是盯住xor这个关键点去 瞎猜 探究有没有什么特殊性质可以使得一些边没有必要建出来. 发现一个点经过一次xor $x$,花费$x$这么多代价(先不看$C$ ...

  2. 进击JavaScript核心 --- (3)面向对象

    JS中的对象定义为:无序属性的结合,其属性可以包含基本值.对象或者函数   1.定义对象的方式   (1).Object构造函数 var student = new Object(); student ...

  3. vue、Element 点击按钮以弹窗形式预览pdf文件

    直接上代码吧 <div > <el-button type="success" size="small" @click="isVie ...

  4. 什么是favicon.ico?

    ㈠定义 ⑴所谓favicon,即Favorites Icon的缩写,顾名思义,便是其可以让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站. ⑵根据浏览器的不同,Favicon显示也有 ...

  5. golang配置oci8所遇到问题解决

    新建文件夹 mingw 将 MinGW.zip 解压到mingw目录下,进入mingw\lib目录下 新建文件夹pkg-config 执行命令 go get github.com/wendal/go- ...

  6. 51 Nod 1101 换零钱(动态规划好题)

    1101 换零钱  基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 ...

  7. Node.js 安装与开发

    Node.js 简介 Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装.Node.js对一些 ...

  8. Java实验课:命令行参数是什么?

    命令行参数:在命令行中给定的参数就是命令行参数.(即从输入位置角度理解). 命令行的参数 1. 什么是命令行的参数? 如: java Test1 365 156 "China" ( ...

  9. JVM系列大纲

    本系列主要分析JVM主要功能要点,初步大纲如下,会根据写作情况进行细化,目的在于梳理JVM的知识体系,具体分析文章会陆续发布. [JVM]类加载机制(1) [JVM]Java内存区域(2) [JVM] ...

  10. 费马小定理证明 (copy的,自己捋清楚)

    费马小定理:假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p) 证明(copy的百度百科,加点自己的解释) 引理1. 若a,b,c为任意3个整数,m为正整数,且(m,c)=1 ...