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.Modelid = 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_lengthsuper(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 RegexValidatorfrom 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 10class 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, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=True)# 可选字段有: bb, code, id, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=False)through=None,               # 自定义第三张表时,使用字段用于指定关系表through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表from django.db import modelsclass 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='0')   # 将指定条件的数据更新,均支持 **kwargs
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
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 osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")import djangodjango.setup()import datetimefrom app01 import modelstry:from django.db import transactionwith transaction.atomic():new_publisher = models.Publisher.objects.create(name="火星出版社")models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社idexcept Exception as e:print(str(e))

转载于:https://www.cnblogs.com/wf123/p/9773840.html

Django 之ORM操作相关推荐

  1. 【Django】ORM操作#2

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

  2. 西游之路——python全栈——Django之ORM操作

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

  3. 第十八 django及ORM操作

    一.项目及ORM操作 1.添加新项目 python manage.py startapp blog 2.配置数据库类 models.py from django.db import models# C ...

  4. Django 数据库ORM 操作 - 字段的类型和参数

    通过Django的ORM创建表的时候,我们需要定义自己的类. 定义类的时候,他有各种各样的字段类型,每个字段都有自己的参数可以进行配置,下面简单的归纳一下. 首先看看字段的类型.尽管Python提供了 ...

  5. Django之ORM操作

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  6. Django中ORM操作

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

  7. Django 使用 ORM 操作数据库详解

    ORM 是个啥? 在python中的一个默认的编写规范是一切皆对象,这样做使得代码简洁,结构清晰,便于维护和重用代码,同时极大的提升开发效率. 同样在操作数据库时,一般我们用SQL语句来实现操作,但是 ...

  8. Django数据库orm操作以list形式获取数据库中某列所有值

    文章目录 问题: 解决办法: 方式一: 方式二: 方式三: 写在最后 问题: 如图所示,Django数据库中存储如下字段. 这是在前端渲染出的数据.现在的需求是:要把factory这一列数据从后端数据 ...

  9. django【orm操作】

    一.ORM表结构 1 class Publisher(models.Model): 2 name = models.CharField(max_length=30, verbose_name=&quo ...

最新文章

  1. Ajax检测注册用户是否存在
  2. 使用Eclipse与Pydev开发Python
  3. python 调用 c 生成数组_python调用c++传递数组的实例
  4. [architecture]-AXI/APB/AHB/ACE的介绍
  5. [翻译]NUnit---Description and Exception Attributes(十一)
  6. linux 连接wifi不稳定,rtl8188ce 无线网不稳定终极解决方案 - 哆啦比猫的技术瞎扯 - Arch Linux · ドラえもん · 实时绘制...
  7. 阿里云超算异构Spot集群,助力深势科技30%成本驱动MDaaS海量算力
  8. 动画库Animate.css
  9. php声明js变量类型,js中变量是什么以及有哪些类型
  10. 手机的哪些功能是几乎没人用的?
  11. iframe调用父页面js方法_JS高级技巧
  12. swift实例教程_Swift示例教程基础
  13. 软硬件兼容性问题学习笔记
  14. 求两条直线(线段)的交点
  15. RHEL 7.0安装配置LAMP服务器(Apache+PHP+MariaDB)
  16. java中函数的调用,java中如何调用函数
  17. 如何判断用户输入的邮箱格式是否正确?
  18. java简易扑克牌游戏设计报告_Java第三季 简易扑克牌游戏 练习完成(已自测通过)...
  19. uniapp引入字体文件
  20. 用户管理和文件权限部分练习题

热门文章

  1. ajax查找错误信息
  2. Django学习记录-1
  3. 响应式设计的十个基本技巧
  4. 风暴数码论坛教程--apk和odex的介绍和合并
  5. “云计算”三部曲之二:与“云”共舞——再谈云计算
  6. NetBeans 时事通讯(刊号 # 27 - Sep 24, 2008)
  7. Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法
  8. 生日QQ配对【找到你生日QQ了吗?】
  9. Java HasCode equals == 的区别
  10. 解决android Stadio 升级之后 出现乱码