ORM:对象关系映射
一、简单操作
定义:面向对象和关系型数据库的一种映射,通过操作对象的方式操作数据
对应关系:
- 类对应数据表
- 对象对应数据行(记录)
- 属性对应字段
导入:from app01 import models
查:
- models.Publisher.objects.all()
- 查询所有的数据,queryset:对象列表
- models.Publisher.objects.get(name='xxxx')
- 对象,获取一个对象(有且唯一),获取不到或者获取到多个对象会报错
- models.Publisher.objects.filter(name='xxxx')
- 获取满足条件的所有的对象,queryset:对象列表
- models.Publisher.objects.all()
增:
- models.Publisher.objects.create(name='xxx')
- 新插入数据库的对象
- obj = models.Publisher(name='xxx')
- 存在在内存中的对象
- obj.save()
- 提交到数据库中,新增
- models.Publisher.objects.create(name='xxx')
删:
- obj = models.Publisher.objects.get(pk=1)
- obj.delete()
- obj_list = models.Publisher.objects.filter(pk=1)
- obj_list.delete()
- obj = models.Publisher.objects.get(pk=1)
改:
- obj = models.Publisher.objects.get(pk=1)
- obj.name = 'new name'
- 在内存中修改对象的属性
- obj.save()
- 提交数据,保存到数据库中
二、 字段
常用字段
- AutoField:自增的整型字段,必填参数primary_key=True
- 注意:一个model不能有两个AutoField字段
- IntegerField:整数类型,数值的范围是 -2147483648 ~ 2147483647
- CharField:字符类型,必须提供max_length参数,max_length表示字符的长度
- DateField:日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例
- 参数:
- auto_now_add=True:新增数据的时候会自动保存当前的时间
- auto_now=True:新增、修改数据的时候会自动保存当前的时间
- 参数:
- DatetimeField:日期时间类型,格式为
YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
,相当于Python中的datetime.datetime的实例 - BooleanField:布尔值类型
- TextField:文本类型
- DecimalField:十进制小数
- 参数:
- max_digits:小数总长度
- decimal_places:小数位总长度
- 参数:
- AutoField:自增的整型字段,必填参数primary_key=True
自定义字段
- 自定义一个char类型字段
class MyCharField(models.Field):
"""
自定义的char类型的字段类
"""
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(MyCharField, self).__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection):
"""
限定生成数据库表的字段类型为char,长度为max_length指定的值
"""
return 'char(%s)' % self.max_length
- 使用自定义char类型字段
class Class(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=25)
# 使用自定义的char类型的字段
cname = MyCharField(max_length=25)
三、 字段参数
- null:数据库中字段是否可以为空
- default:数据库中字段的默认值
- primary_key:数据库中字段是否为主键
- db_index:数据库中字段是否可以建立索引
- unique:数据库中字段是否可以建立唯一索引
- blank:Admin中是否允许用户输入为空
- choices:Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
- choices=((0, '女'), (1, '男') :可填写的内容和提示
四、 Model Meta参数
在表对于的类中写入一个类Meta
class UserInfo(models.Model):
nid = models.AutoField(primary_key=True)
username = models.CharField(max_length=32) class Meta:
# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
db_table = "table_name"
# admin中显示的表名称
verbose_name = '个人信息'
# verbose_name加s
verbose_name_plural = '所有用户信息'
# 联合索引
index_together = [
("pub_date", "deadline"), # 应为两个存在的字段
]
# 联合唯一索引
unique_together = (("driver", "restaurant"),) # 应为两个存在的字段
五、 ORM操作——必知必会13条
- all():查询所有结果,返回QuerySet对象
- get():返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误,返回单个对象
- filter():返回所有符合条件的对象,返回QuerySet对象
- exclude():返回所有不符合条件的对象,返回QuerySet对象
- values('字段'):拿到对象指定的字段和字段的值,返回的是一个字典序列,返回QuerySet对象
- values_list('字段'):拿到对象指定的字段的值,返回的是一个元组序列,返回QuerySet对象
- order_by():对查询结果排序,默认升序,字段前加负号则为降序,返回QuerySet对象
- order_by('age','-pid'):先按age字段升序排列,再按pid字段降序排列
- reverse():对查询结果反向排序,只能对已经排序的QuerySet进行反转,返回QuerySet对象
- distinct():对查询结果进行去重,完全相同的内容才能去重,返回QuerySet对象
- count():计数,返回数据库中匹配查询的对象数量,返回数字
- first():返回第一条记录,即取第一个元素,没有返回None,返回单个对象
- last():返回最后一条记录,即取最后一个元素,没有返回None,返回单个对象
- exist():判断查询的数据是否存在,存在返回True,否则返回False,返回布尔值
总结:
# 返回的是queryset对象的
all()
filter()
exclude()
values()
values_list()
order_by()
reverse()
distinct()
# 返回的是单个对象的
get()
first()
last()
# 返回的是数字的
count()
# 返回的是布尔值的
exists()
六、 单表查询的双下划线
- 条件判断,相当于SQL中的while
- __gt:大于
- ret = models.Person.objects.filter(pk__gt=1)
- 获取pk大于1的
- ret = models.Person.objects.filter(pk__gt=1)
- __lt:小于
- ret = models.Person.objects.filter(pk__lt=3)
- 获取pk小于3的
- ret = models.Person.objects.filter(pk__lt=3)
- __gte:大于等于
- ret = models.Person.objects.filter(pk__gte=1)
- 获取pk大于等于1的
- ret = models.Person.objects.filter(pk__gte=1)
- __lte:小于等于
- ret = models.Person.objects.filter(pk__lte=3)
- 获取pk小于等于3的
- ret = models.Person.objects.filter(pk__lte=3)
- __gt:大于
- __range:范围查询,相当于SQL的between...and...
- ret = models.Person.objects.filter(pk__range=[1,3])
- 获取pk范围是1到3的
- ret = models.Person.objects.filter(pk__range=[1,3])
- __in:成员判断
- ret = models.Person.objects.filter(pk__in=[1,3])
- 获取pk等于1、3的,相当于SQL的 in
- ret = models.Person.objects.exclude(pk__in=[1,3])
- 获取pk不等于1和3的,相当于SQL的 not in
- ret = models.Person.objects.filter(pk__in=[1,3])
- 模糊查询:相当于SQL的 like 和正则匹配
- __contains:模糊查询
- ret = models.Person.objects.filter(name__contains='A')
- 获取name字段的值包含'A'的
- ret = models.Person.objects.filter(name__contains='A')
- __icontains:在contains的基础上,对条件中的字母大小写不敏感
- ret = models.Person.objects.filter(name__icontains='A')
- 获取name字段的值包含'A'或'a'的,忽略大小写
- ret = models.Person.objects.filter(name__icontains='A')
- __contains:模糊查询
- 判断以...开头/结尾
- __startswith:以...开头
- ret = models.Person.objects.filter(name__startswith='A')
- 获取name字段的值以'A'开头的
- ret = models.Person.objects.filter(name__startswith='A')
- __istartswith:在startswith的基础上,对条件中的字母大小写不敏感
- ret = models.Person.objects.filter(name__istartswith='A')
- 获取name字段的值以'A'或'a'开头的,忽略大小写
- ret = models.Person.objects.filter(name__istartswith='A')
- __endswith:以...结尾
- ret = models.Person.objects.filter(name__endswith='A')
- 获取name字段的值以'A'结尾的
- ret = models.Person.objects.filter(name__endswith='A')
- __iendswith:在endswith的基础上,对条件中的字母大小写不敏感
- ret = models.Person.objects.filter(name__iendswith='A')
- 获取name字段的值以'A'或'a'结尾的,忽略大小写
- ret = models.Person.objects.filter(name__iendswith='A')
- __startswith:以...开头
- __year:判断日期年份
- ret = models.Person.objects.filter(birth__year='2019')
- 获取birth字段的值的年份是2019的
- __year只能筛选年份,如果要筛选年月日,使用contains:模糊查询
- ret = models.Person.objects.filter(birth__contains='2018-06-24')
- 获取birth字段的值是2018-06-24的
- ret = models.Person.objects.filter(birth__contains='2018-06-24')
- ret = models.Person.objects.filter(birth__year='2019')
- __isnull:查询与null的项
- __isnull = True:查询值是null的
- ret = models.Person.objects.filter(phone__isnull=True)
- 获取phone字段的值是null的
- ret = models.Person.objects.filter(phone__isnull=True)
- __isnull = False:查询值不是null的
- __isnull = True:查询值是null的
七、 ForeignKey操作
基于对象的查询
- 正向查询,语法:对象.关联字段.字段
book_obj = models.Book.objects.get(title='菊花怪大战MJJ')
book_obj.pub
book_obj.pub.name
- 反向查询,语法:对象.表名_set.all(),表名即类名小写
- 设置ForeignKey的参数:related_name,相当于替换了类名小写_set
pub_obj = models.Publisher.objects.get(pk=1)
# 没有指定related_name,使用类名小写_set
pub_obj.book_set.all()
# 指定related_name='books'
pub_obj.books.all()
基于字段的查询
- 正向查询,语法:关联字段__字段
# 查询老男孩出版的书
ret = models.Book.objects.filter(pub__name='老男孩出版社')
- 反向查询,语法:表名__字段
- 设置ForeignKey的参数:related_query_name,相当于替换了表名
# 查询出版菊花怪大战MJJ的出版社
# 没有指定related_name,使用类名的小写
ret= models.Publisher.objects.filter(book__title='菊花怪大战MJJ')
# related_name='books'
ret= models.Publisher.objects.filter(books__title='菊花怪大战MJJ')
# related_query_name='xxx'
ret= models.Publisher.objects.filter(xxx__title='菊花怪大战MJJ')
八、 多对多的操作
基于对象的查询
- 正向查询,语法:对象.多对多字段.all()
mjj = models.Author.objects.get(pk=1)
mjj.books # 关系管理对象
mjj.books.all()
- 反向查询,语法:对象.类名小写_set.all()
- 设置related_name,相当于替换了类名小写_set
book_obj = models.Book.objects.filter(title='桃花侠大战菊花怪').first()
# 不指定related_name
book_obj.author_set # 关系管理对象
book_obj.author_set.all()
# 指定related_name='authors'
book_obj.authors # 关系管理对象
book_obj.authors.all()
基于字段的查询
- 正向查询,语法:多对多字段__字段
ret = models.Author.objects.filter(books__title='菊花怪大战MJJ')
- 反向查询,语法:类名小写__字段
- 设置related_query_name,相当于替换了类名小写
# 不指定related_name
ret = models.Book.objects.filter(author__name='MJJ')
# 指定related_name='authors'
ret = models.Book.objects.filter(authors__name='MJJ')
# 指定related_query_name='xxx'
ret = models.Book.objects.filter(xxx__name='MJJ')
关系管理对象的方法
- all():所关联的所有对象
mjj = models.Author.objects.get(pk=1)
mjj.books.all()
- set():设置多对多关系
# set() [id,id] [对象,对象]
mjj.books.set([1,2])
mjj.books.set(models.Book.objects.filter(pk__in=[1,2,3]))
- add():添加多对多关系
# add (id,id) (对象,对象)
mjj.books.add(4,5)
mjj.books.add(*models.Book.objects.filter(pk__in=[4,5]))
- remove():删除多对多关系
# remove (id,id) (对象,对象)
mjj.books.remove(4,5)
mjj.books.remove(*models.Book.objects.filter(pk__in=[4,5]))
- clear():清除所有多对多关系
mjj.books.clear()
- create():创建多对多关系
obj = mjj.books.create(title='跟MJJ学前端',pub_id=1) book__obj = models.Book.objects.get(pk=1)
obj = book__obj.authors.create(name='taibai')
九、 聚合和分组
聚合
- 内置函数:Max(最大值)、Min(最小值)、Avg(平均值)、Sum(求和)、Count(计数)
from app01 import models
from django.db.models import Max, Min, Avg, Sum, Count
# 为聚合值指定名称,注意关键字传参要在位置传参后面
ret = models.Book.objects.filter(pk__gt=3).aggregate(Max('price'),avg=Avg('price'))
print(ret)
分组
- 一般和聚合一起使用
# 统计每一本书的作者个数,annotate:注释
ret = models.Book.objects.annotate(count=Count('author')) # 统计出每个出版社的最便宜的书的价格
# 方式一
ret = models.Publisher.objects.annotate(Min('book__price')).values()
# 方式二:objects后面接values,就是按字段分组,相当于分组条件
ret = models.Book.objects.values('pub_id').annotate(min=Min('price'))
十、 F查询和Q查询
F查询
from django.db.models import F
# 比较两个字段的值
ret=models.Book.objects.filter(sale__gt=F('kucun')) # 只更新sale字段
models.Book.objects.all().update(sale=100) # 取某个字段的值进行操作
models.Book.objects.all().update(sale=F('sale')*2+10)
Q查询
- 条件符号:&(与)、|(或)、~(非)
from django.db.models import Q
ret = models.Book.objects.filter(~Q(Q(pk__gt=3) | Q(pk__lt=2)) & Q(price__gt=50))
print(ret)
十一、 事务
使用try进行回滚时,必须把try写在with的外面,否则无法回滚
from django.db import transaction try:
with transaction.atomic():
# 进行一系列的ORM操作
models.Publisher.objects.create(name='xxxxx')
models.Publisher.objects.create(name='xxx22')
except Exception as e :
print(e)
十二、 其他操作设置
Django ORM执行原生SQL
# 执行原生SQL
# 更高灵活度的方式执行原生SQL语句
from django.db import connection, connections
cursor = connection.cursor()
cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
Django终端打印SQL语句
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
在Python中脚本中调用Django环境
- 在要执行的py文件中写入
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
# orm_practice.settings表示当前项目的settings.py,orm_practice是当前项目名称
import django
django.setup() from app01 import models
# 再继续写要执行的语句,例如
books = models.Book.objects.all()
print(books)
ORM:对象关系映射的更多相关文章
- ORM 对象关系映射
ORM (object relation mapping) 就是将对象数据转换为sql语句并执行 对象关系映射框架 orm 需要做的事情 1 生成创建表的语句 2 插入数据的语句 3 删除数据的语句 ...
- Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点)
Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点) 一丶Django的静态文件配置 #we ...
- Php ORM 对象关系映射
ORM的全称是Object Relational Mapping,即对象关系映射.它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将 ...
- $Django setting.py配置 ,GET、POST深入理解,三件套,orm对象关系映射简介
1 django中app的概念: 大学:----------------- 项目 信息学院 ----------app01 物理学院-----------app02 ****强调***:创建的每一 ...
- ORM对象关系映射
ORM 总结: ORM:对象关系映射 作用: 1.将定义数据库模型类--> 数据库表 2.将定义数据库模型类中的属性--->数据库表字段 3.将模型对象的操作(add,delete,com ...
- Java 自定义注解实现ORM对象关系映射
一,ORM概念 ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关 ...
- django-模型之(ORM)对象关系映射(一)
所谓对象关系映射,就是将数据库的一些名字与python中的一些名字相对应,表名-->类名,字段-->属性,操作(增删改查)-->方法.这样,我们就可以通过对Python代码的编辑来对 ...
- ORM对象关系映射之GreenDAO源码解析
上一篇我们学习了GreenDAO的CRUD基本操作,可以说是非常的方便的,而且GreenDAO的效率和性能远远高于其它两款流行的ORM框架,下面是我从官网找的一副它们三个ORM框架之间的性能测试的直观 ...
- Python Web框架篇:Django Model ORM(对象关系映射)
一,基本操作 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 1.增(create , save): from app01 ...
- ORM对象关系映射之使用GreenDAO进行CRUD操作
在Android中,我们都知道使用的数据库是SQLite,而使用这种原生的数据库非常繁琐,它对表的管理和进行CRUD操作都需要我们写sql语句,在进行多表关联的操作上,更是需要写一堆sql,而且维护起 ...
随机推荐
- MySQL执行SQL脚本问题 :错误代码2006、1153
今天用mysql执行了一个60M的SQL脚本遇到了一些错误,经由网上查询如下: 1.#2006 - MySQL server has gone away 出现该错误代码原因如下: 1.应用程序长时间的 ...
- Linux—编译安装详解
编译安装python3 1.python是通过C语言编写,所以在编译安装python3时需要在C语言环境 [root@localhost ~]# yum install -y gcc 2.python ...
- python爬虫(2)——urllib、get和post请求、异常处理、浏览器伪装
urllib基础 urlretrieve() urlretrieve(网址,本地文件存储地址) 直接下载网页到本地 import urllib.request #urlretrieve(网址,本地文件 ...
- 20191028 Codeforces Round #534 (Div. 1) - Virtual Participation
菜是原罪. 英语不好更是原罪. \(\mathrm{A - Grid game}\) 题解 \(4 \times 4\) 的格子,两种放法. 发现这两种在一起时候很讨厌,于是强行拆分这个格子 上面 \ ...
- MySQL的delete误操作的快速恢复方法
1. 根据误操作时间定位binlog位置找到数据库的binlog存放位置,当前正在使用的binlog文件里面就有我们要恢复的数据.一般生产环境中的binlog文件都是几百M乃至上G的大小,我们不能逐行 ...
- 洛谷P4169 [Violet]天使玩偶/SJY摆棋子
%%%神仙\(SJY\) 题目大意: 一个二维平面,有两种操作: \(1.\)增加一个点\((x,y)\) \(2.\)询问距离\((x,y)\)曼哈顿最近的一个点有多远 \(n,m\le 300 0 ...
- x1
//程序功能: //要求客户从键盘输入一个整数,判断其是奇是偶 #include <stdio.h> int main(){ int x; printf("输入一个整数:\n&q ...
- Paper | Fast image processing with fully-convolutional networks
目录 故事 方法 实验 发表在2017年ICCV. 核心任务:加速图像处理算子(accelerate image processing operators). 核心方法:将算子处理前.后的图像,训练一 ...
- JAVA基础系列:反射
1. 定义 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这 种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. ...
- python命令行解析函数
sys.argv 在终端运行python 1.py hahah import sys print(sys.argv) # ['1.py', 'hahah'] argparse Python的命令行解析 ...