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操作的更多相关文章

  1. Django之ORM操作

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

  2. Django之ORM操作(聚合 分组、F Q)

    Django之ORM操作(聚合 分组.F Q) 聚合 aggregate()是QuerySet的一个终止子句,也就是说,他返回一个包含一些键值对的字典,在它的后面不可以再进行点(.)操作.   键的名 ...

  3. Django之ORM操作(***)

    Django之ORM操作(***) http请求的流程: url--> 视图view(模板+数据库) --> ORM的功能: 可以转换SQL语句,并做操作. ORM操作数据表: -创建表: ...

  4. 【Django】ORM操作#2

    目录 必知必会的13条查询方法 单表查询之神奇的双下划线 一对多 ForeignKey 多对多 ManyToManyField 在Python脚本中调用Django环境 Django终端打印SQL语句 ...

  5. 【Django】ORM操作#1

    目录 一.介绍 概念 由来 优势 劣势 总结 二.Django中的ORM Django项目使用MySQL Model 快速入门 1. AutoField 2. IntegerField 3. Char ...

  6. django的orm操作优化

    django的orm操作优化 models.py from django.db import models class Author(models.Model): name = models.Char ...

  7. Django中ORM操作

    ORM操作: class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.Ch ...

  8. Django的ORM操作

    ORM操作 select * from tb where id > 1 # 对应关系 models.tb.objects.filter(id__gt=1) models.tb.objects.f ...

  9. Django之ORM操作总结

    Django之ORM总结 表结构 from django.db import models # 一对多:班级与学生 # 多对多:班级与老师 # Create your models here. #创建 ...

  10. Django之ORM操作(重要)

    Django ORM操作 一般操作 看专业的官网文档,做专业的程序员! 必知必会13条   <1> all(): 查询所有结果 <2> get(**kwargs): 返回与所给 ...

随机推荐

  1. 【转】OPC远程访问相关配置信息

    原文:http://blog.gkong.com/kking_25653.ashx 对于远程访问OPC服务器,需要在客户和服务器计算机上都进行DCOM设置,本文提供一些具体配置方法.(by Kevin ...

  2. Working out (DP)

    Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the ...

  3. 用KMP征服循环节问题

    以前我还是写过KMP的文章的 现在我们可以求一下循环节啊 Slot Machines Gym - 101667I #include<bits/stdc++.h> using namespa ...

  4. Terracotta

    Terracotta 3.2.1简介 (一) 博客分类: 企业应用面临的问题 Java&Socket 开源组件的应用 hibernatejava集群服务器EhcacheQuartzTerrac ...

  5. JSF框架整理

    JSP体系结构: JSF主要优势之一就是它既是Java web 应用程序的用户界面标准又是严格遵循 模型-视图-控制器(MVC)设计模式的框架. 用户界面代码(视图)和应用程序数据和逻辑(模型)的清晰 ...

  6. 【2018.10.1】【JSOI2016】最佳团体(bzoj4753)

    一看到“比值”最大(性价比最高)就知道跟分数规划有关系了.(这里讲过分数规划) 然后看到 要选一个候选人 必须选他的前置,画画图就知道是一棵树. 所以这道题是二分比值,每个点的权值就是战斗力-费用*比 ...

  7. VMware虚拟机CentOS7 - VMnet8网络配置及常见问题解决

    本文环境 物理机OS: Windows10 专业版 虚拟机平台: VMware Workstation 14 虚拟机OS: CentOS 7 配置步骤 一. 查看物理主机的网络配置信息 主要是找到可以 ...

  8. 标准C程序设计七---17

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...

  9. 2014湘潭全国邀请赛I题 Intervals /POJ 3680 / 在限制次数下取有权区间使权最大/小问题(费用流)

    先说POJ3680:给n个有权(权<10w)开区间(n<200),(区间最多数到10w)保证数轴上所有数最多被覆盖k次的情况下要求总权最大,输出最大权. 思路:       限制的处理:s ...

  10. 2017-10-29-morning-清北模拟赛

    T1 遭遇 #include <algorithm> #include <cstdio> #include <cmath> inline void read(int ...