Django 之ORM操作
1、什么是ORM?
全称关系对象映射Object Relational Mapping(简称ORM),是通过描述面向对象与数据库之间的对应的元数据,将对象持久化的更新到数据库中。
有了ORM,就不需要自己去手写SQL语句,ORM会根据编写的面向对象代码自动翻译成SQL语句,提高开发效率,但是处理数据的能力不是最优的。
2、映射关系
3、在Django项目中,使用ORM前的一些配置操作
1、手动创建一个数据库
2、在Django项目中的settings.py文件中,找到这个字段,改成如下格式
- DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.mysql",
- "NAME": "你的数据库名称", # 需要自己手动创建数据库
- "USER": "数据库用户名",
- "PASSWORD": "数据库密码",
- "HOST": "数据库IP",
- "POST": 3306
- }
- }
3、在settings.py同级目录中的__init__.py文件中,导入pymysql
- import pymysql
- pymysql.install_as_MySQLdb()
4、在Django项目下的app包下的models文件中,创建类,这个类就是要与数据库进行对应的那个映射关系。
- from django.db import models #导入models模块
- class Class(models.Model): #继承models.Model
- id = models.AutoField(primary_key=True)
- Class_name = models.CharField(max_length=32)
5、在models中有变更,需要执行两条命令来保证数据库与对象之间的对应
·1
- python manage.py makemigrations
- # 记录models的变更
·2
- python manage.py migrate
- # 将models中的代码翻译成SQL语句,同步到数据库中
4、常用字段
AutoField:
自增长字段,必填参数为(primary_key=True)设置成主键。不写的时候,Django会自动创建。一个类中不能出现两个AutoField字段。
CharField:
字符串类型,必须提供max_length参数,表示字符串的最大长度。
IntegerField:
整数类型,数值范围-2147483646~2147483646
DataField
日期类型,日期格式为YYYY-MM-DD
参数:
·auto_now:每次修改时修改为当前的时间
·auto_now_add:新创建对象时自动添加当前时间
auto_now 和 auto_now_add 和 default参数是互斥的,不能够同时设置。
DatatimeField
日期类型,与DataField不同的是,增加了时分秒。
格式为YYYY-MM-DD HH:MM:ss
5、自定义字段
我们可以自己去定义字段来使用,例如自定义一个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
使用自定义字段
- class Class(models.Model):
- id = models.AutoField(primary_key=True)
- title = models.CharField(max_length=25)
- # 使用自定义的char类型的字段
- cname = MyCharField(max_length=25)
6、字段参数
我们在定义某个字段的时候,可以有多个参数,比如null=True表示允许该字段可以为空,等等,下面就是一些字段的参数
- null 数据库中字段是否可以为空
- db_column 数据库中字段的列名
- default 数据库中字段的默认值
- primary_key 数据库中字段是否为主键
- db_index 数据库中字段是否可以建立索引
- unique 数据库中字段是否可以建立唯一索引
- unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
- unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
- unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
- verbose_name Admin中显示的字段名称
- blank Admin中是否允许用户输入为空
- editable Admin中是否可以编辑
- help_text Admin中该字段的提示信息
- choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
- 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
- error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
- 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
- 如:{'null': "不能为空.", 'invalid': '格式错误'}
- validators 自定义错误验证(列表类型),从而定制想要的验证规则
- from django.core.validators import RegexValidator
- from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
- MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
- 如:
- test = models.CharField(
- max_length=32,
- error_messages={
- 'c1': '优先错信息1',
- 'c2': '优先错信息2',
- 'c3': '优先错信息3',
- },
- validators=[
- RegexValidator(regex='root_\d+', message='错误了', code='c1'),
- RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
- EmailValidator(message='又错误了', code='c3'), ]
- )
字段参数
7、多表关系和参数
- ForeignKey(ForeignObject) # ForeignObject(RelatedField)
- to, # 要进行关联的表名
- to_field=None, # 要关联的表中的字段名称
- on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- - models.CASCADE,删除关联数据,与之关联也删除
- - models.DO_NOTHING,删除关联数据,引发错误IntegrityError
- - models.PROTECT,删除关联数据,引发错误ProtectedError
- - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
- - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
- - models.SET,删除关联数据,
- a. 与之关联的值设置为指定值,设置:models.SET(值)
- b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
- def func():
- return 10
- class MyModel(models.Model):
- user = models.ForeignKey(
- to="User",
- to_field="id"
- on_delete=models.SET(func),)
- related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
- related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
- limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
- # 如:
- - limit_choices_to={'nid__gt': 5}
- - limit_choices_to=lambda : {'nid__gt': 5}
- from django.db.models import Q
- - limit_choices_to=Q(nid__gt=10)
- - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
- db_constraint=True # 是否在数据库中创建外键约束
- parent_link=False # 在Admin中是否显示关联数据
- OneToOneField(ForeignKey)
- to, # 要进行关联的表名
- to_field=None # 要关联的表中的字段名称
- on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- ###### 对于一对一 ######
- # 1. 一对一其实就是 一对多 + 唯一索引
- # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
- # 如下会在A表中额外增加一个c_ptr_id列且唯一:
- class C(models.Model):
- nid = models.AutoField(primary_key=True)
- part = models.CharField(max_length=12)
- class A(C):
- id = models.AutoField(primary_key=True)
- code = models.CharField(max_length=1)
- ManyToManyField(RelatedField)
- to, # 要进行关联的表名
- related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
- related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
- limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
- # 如:
- - limit_choices_to={'nid__gt': 5}
- - limit_choices_to=lambda : {'nid__gt': 5}
- from django.db.models import Q
- - limit_choices_to=Q(nid__gt=10)
- - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
- symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
- # 做如下操作时,不同的symmetrical会有不同的可选字段
- models.BB.objects.filter(...)
- # 可选字段有:code, id, m1
- class BB(models.Model):
- code = models.CharField(max_length=12)
- m1 = models.ManyToManyField('self',symmetrical=True)
- # 可选字段有: bb, code, id, m1
- class BB(models.Model):
- code = models.CharField(max_length=12)
- m1 = models.ManyToManyField('self',symmetrical=False)
- through=None, # 自定义第三张表时,使用字段用于指定关系表
- through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
- from django.db import models
- class Person(models.Model):
- name = models.CharField(max_length=50)
- class Group(models.Model):
- name = models.CharField(max_length=128)
- members = models.ManyToManyField(
- Person,
- through='Membership',
- through_fields=('group', 'person'),
- )
- class Membership(models.Model):
- group = models.ForeignKey(Group, on_delete=models.CASCADE)
- person = models.ForeignKey(Person, on_delete=models.CASCADE)
- inviter = models.ForeignKey(
- Person,
- on_delete=models.CASCADE,
- related_name="membership_invites",
- )
- invite_reason = models.CharField(max_length=64)
- db_constraint=True, # 是否在数据库中创建外键约束
- db_table=None, # 默认创建第三张表时,数据库中表的名称
多表关系和参数
8、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.exclude(name='seven') # 去除指定条件的数据
- # 删
- # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
- # 改
- models.Tb1.objects.filter(name='seven').update(gender='') # 将指定条件的数据更新,均支持 **kwargs
- obj = models.Tb1.objects.get(id=1)
- obj.c1 = ''
- obj.save() # 修改单条数据
9、13条方法
1、返回对象列表,返回的是一个QuerySet对象 <QuerySet [ ]>
all() 查询所有结果
filter(筛选条件) 筛选
exclude(条件) 查询除了该条件以外的其他对象
order_by() 排序,默认是升序,oder_by(-'price')加负号为降序
reverse() 降序
distinct() 去重
values() 返回一个ValueQuerySet------一个特殊的QuerSet,values返回的是一个字典,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典。
values_list() 获取到的是对象的值,拿到的是一个元祖
2、获取对象
get() 获取到的是一个对象,并且有且只有一个
first() 获取到第一个对象
last() 获取到最后一个对象
3、返回数字
count() 计数,返回数据库中匹配查询的对向数量
4、返回布尔值
exists() 判断存不存在,如果QuerySet包含数据,就返回True,否则返回False
10、单表查询的双下方法
1、id__lt=10 id小于10的
2、id__gt=10 id大于10的
3、id__lte=10 id小于等于10
id__gte=10 id大于等于10
4、id__in=[···] id在这个列表中的
5、id__range=[1,3] id范围在1到3的
6、name__contains = 'wb' 获取name字段包含'wb'所有满足条件的字段
7、name__startswith() 以·····开头
name__istartswith() 以·····开头,不区分大小写
8、name__endswith() 以·····结尾
name__iendswith() 以·····结尾,不区分大小写
9、xx__year=2017 找到年份是2017年的
11、ForeignKey操作
一、
1、对象查询
语法:对象.关联字段.字段
示例:
- book_obj = models.Book.objects.first() # 第一本书对象
- print(book_obj.publisher) # 得到这本书关联的出版社对象
- print(book_obj.publisher.name) # 得到出版社对象的名称
2、字段查询
语法:
关联字段__字段
示例:
- print(models.Book.objects.values_list("publisher__name"))
二、反向操作
何为反向操作?
如果A对B设了外键,那么从A查询B就属于正向查询,B查询A就是反向查询
1、对象查找
语法:
obj.表明_set
示例:
- publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象
- books = publisher_obj.book_set.all() # 找到第一个出版社出版的所有书
- titles = books.values_list("title") # 找到第一个出版社出版的所有书的书名
2、字段查找
语法:
表明_字段
示例:
- titles = models.Publisher.objects.values_list("book__title")
12、ManyToManyField
方法:
1、create()
创建一个新对象,保存对象,并将它添加到关联对象中,返回新创建的对象。
- >>> import datetime
- >>> models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())
2、add()
把制定的model对象添加到关联对象中。
添加对象
- >>> author_objs = models.Author.objects.filter(id__lt=3)
- >>> models.Book.objects.first().authors.add(*author_objs)
添加id
- >>> models.Book.objects.first().authors.add(*[1, 2])
3、set()
更新model对象的关联对象
- >>> book_obj = models.Book.objects.first()
- >>> book_obj.authors.set([2, 3])
4、remove()
从关联对象集中移除执行的model对象
- >>> book_obj = models.Book.objects.first()
- >>> book_obj.authors.remove(3)
5、clear()
从关联对象集中移除一切对象
- >>> book_obj = models.Book.objects.first()
- >>> book_obj.authors.clear()
注意:对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
如果ForeignKey字段不设置null=True时,就没有clear()和remove()方法。
6、总结
对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要在调用save()方法。
13、聚合查询
1、aggregate()是QuerySet()的一个终止字句,意思是,它之后不能再有链式操作。返回的是一个包含一些键值对的字典。生成的字典的key是查询的字段和聚合函数的名称自动拼接组成的,也可以进行重新命名。
2、可能用到的聚合函数:
- from django.db.models import Avg, Sum, Max, Min, Count
示例:
- >>> from django.db.models import Avg, Sum, Max, Min, Count
- >>> models.Book.objects.all().aggregate(Avg("price"))
- {'price__avg': 13.233333} #得到的结果是个字典,key进行了自动拼接
如果想要进行重命名,可以向聚合子句提供。
- >>> models.Book.objects.aggregate(average_price=Avg('price')) #用average_price重新命名,这样就不会有自动生成的名字了
- {'average_price': 13.233333}
3、如果想要生成多个聚合,可以向aggregate()子句中添加多个参数。比如,如果你除了想知道书籍的平均值还想知道图书馆中价格最大和最小的书籍的价格,可以这样查询:
- >>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
- {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
14、分组
1、分组就是将事务进行一个区分,归类。比如班级的学生,以性别分组,就会分为男生和女生,按年龄段分组,就会分成多个年龄段的。
2、用annotate()分组,annotate()之前的是按照什么分组,括号里写的是聚合函数
3、例子
如果使用原生的SQL语句,按照部门分组求平均工资:
- select dept,AVG(salary) from employee group by dept;
ORM查询:
- from django.db.models import Avg
- Employee.objects.values("dept").annotate(avg=Avg("salary").values("dept", "avg")
连表查询的分组
SQL语句查询
- select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;
ORM查询:
- from django.db.models import Avg
- models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")
15、F查询
F可以动态地获取到一个字段的值
- from django.db.models import F # 从django数据库中导入F
- models.Book.objects.filter(commnet_num__gt=F('keep_num'))
- # F('keep_num')动态的获取到'keep_num'的值
Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作
- models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)
修改操作也可以使用F函数,比如将每一本书价格+30
- models.Book.objects.all().update(price=F("price")+30)
16、Q查询
当查询某些数据需要用到‘或’的时候,就需要Q查询。
示例:
1、查询作者名是小狐仙或者小仙女的
- models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))
2、也可以结合 & 和 | 以及括号分组来进行任意操作。还可以用~进行取反
查询作者名字是小仙女并且不是2018年出版的书的书名
- >>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
- <QuerySet [('番茄物语',)]>
17、事务
1、什么是事务?
比如一件事情,有好多步骤,每个步骤组合起来就是一个事务。在django中,用transaction表示。
2、事务的特点
只有两种可能,要么生,要么死。一个事务要想成功,就必须是每一个步骤全都成功,如果有一个失败,就全都失败,并将成功的分步骤,全不回退。
3、示例
- import os
- if __name__ == '__main__':
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
- import django
- django.setup()
- import datetime
- from app01 import models
- try:
- from django.db import transaction
- with transaction.atomic():
- new_publisher = models.Publisher.objects.create(name="火星出版社")
- models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
- except Exception as e:
- print(str(e))
Django 之ORM操作的更多相关文章
- Django之ORM操作
Django之ORM操作 前言 Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计 ...
- Django之ORM操作(聚合 分组、F Q)
Django之ORM操作(聚合 分组.F Q) 聚合 aggregate()是QuerySet的一个终止子句,也就是说,他返回一个包含一些键值对的字典,在它的后面不可以再进行点(.)操作. 键的名 ...
- Django之ORM操作(***)
Django之ORM操作(***) http请求的流程: url--> 视图view(模板+数据库) --> ORM的功能: 可以转换SQL语句,并做操作. ORM操作数据表: -创建表: ...
- 【Django】ORM操作#2
目录 必知必会的13条查询方法 单表查询之神奇的双下划线 一对多 ForeignKey 多对多 ManyToManyField 在Python脚本中调用Django环境 Django终端打印SQL语句 ...
- 【Django】ORM操作#1
目录 一.介绍 概念 由来 优势 劣势 总结 二.Django中的ORM Django项目使用MySQL Model 快速入门 1. AutoField 2. IntegerField 3. Char ...
- django的orm操作优化
django的orm操作优化 models.py from django.db import models class Author(models.Model): name = models.Char ...
- Django中ORM操作
ORM操作: class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.Ch ...
- Django的ORM操作
ORM操作 select * from tb where id > 1 # 对应关系 models.tb.objects.filter(id__gt=1) models.tb.objects.f ...
- Django之ORM操作总结
Django之ORM总结 表结构 from django.db import models # 一对多:班级与学生 # 多对多:班级与老师 # Create your models here. #创建 ...
- Django之ORM操作(重要)
Django ORM操作 一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给 ...
随机推荐
- 【Android】SharedPreference存储数据
SharedPreference存储数据 使用SharedPreference保存数据 putString(key,value) 使用SharedPreference读取数据 getString( ...
- BZOJ 4001 [TJOI2015]概率论 ——找规律
题目太神了,证明还需要用到生成函数. 鉴于自己太菜,直接抄别人的结果好了. #include <map> #include <cmath> #include <queue ...
- BZOJ 3282 Tree ——Link-Cut Tree
[题目分析] 明显的LCT维护连通性的题目. access的操作是比较巧妙的,可以把结点到根变成偏爱路径,而且保证了该点是链上深度最深的点. 而且需边的思想也很巧妙,保证了复杂度. 但是只能用于修改路 ...
- [HDU-5536] Chip Factory (01字典树)
Problem Description John is a manager of a CPU chip factory, the factory produces lots of chips ever ...
- Spring JdbcTemplate 与 事务管理 学习
Spring的JDBC框架能够承担资源管理和异常处理的工作,从而简化我们的JDBC代码, 让我们只需编写从数据库读写数据所必需的代码.Spring把数据访问的样板代码隐藏到模板类之下, 结合Sprin ...
- LA 4728 旋转卡壳算法求凸包的最大直径
#include<iostream> #include<cstdio> #include<cmath> #include<vector> #includ ...
- elasticsearch入门使用(一)es 6.2.2安装,centos 7
elasticsearch(一般叫es)是基于Lucene的搜索服务器,提供http协议接口使用json格式数据,也提供相应的客户端,更详细的信息[优点&场景]请百度百科, 以下官网截图,官网 ...
- HUNAN 11569 Just Another Knapsack Problem(AC自动机+dp)
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11569&courseid=0 给出目标串,每个子串和 ...
- Debian9初始配置
1 进入root用户 su root 2 修改镜像源:编辑/etc/apt/sources.list文件 nano /etc/apt/sources.list 修改内容如下: deb http://m ...
- POJ 1509 Glass Beads【字符串最小表示法】
题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...