ORM是什么
ORM实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于数据库,通过简单的配置就可以轻松更换数据库,这减轻了开发人员的工作量.
对象和关系型数据库的映射
必会13条:
1. 返回对象列表的
all() Book.objects.all()
filter()
exclude()
order_by()
reverse()
distinct()
values() {}
values_list() ()
2. 获取对象的
get()
first()
last()
3. 返回数字
count()
4. 返回布尔值
exists()
单表双下:
基于双下划线的模糊查询,单表中双下表示比较这个字段.
Book.objects.filter(price__in=[100,200,300]) #price在这个列表内的 Book.objects.filter(price__gt=100) #price大于100 Book.objects.filter(price__lt=100) ##price小于100 Book.objects.filter(price__range=[100,200]) #pirce在100到200之间 Book.objects.filter(title__contains="python") # 模糊查询titile包含ptyhon,区分大小写 Book.objects.filter(title__icontains="python") # 不区分大小写 Book.objects.filter(title__startswith="py") #title以py开头 Book.objects.filter(pub_date__year=2012) #pub_data是2012年的 Book.objects.filter(pub_date__year__gt=2012) #pub_data是2012年后的
id__gt
id__lt
id__lte
id__gte
id__in=[]
id__range=[1,4]
contains= ''
icontains= ''
startswith = ''
istartswith = ''
endswith = ''
iendswith = ''
isnull = True
__year
FK外键
publish=models.ForeignKey(to="Publish",to_field="nid",relate_name="xxx",on_delete=models.CASCADE)
m2m 多对多
authors=models.ManyToManyField(to='Author') #authors不是一个真实的字段.只是ORM层面建立的一个多对多关系.用authors关联作者表.
author_obj.books --》管理对象
author_obj.books.add()
author_obj.books.remove()
author_obj.books.clear()
author_obj.books.set() []
author_obj.books.create()
book_obj.authors --》管理对象
跨表双下
正相查
反向查
聚合
#查书的平均价格
Book.objects.all().aggregate(AVG("price"))
#查书的最高价,最低价
Book.objects.aggregate( Max('price'), Min('price'))
分组
跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询
Employee.objects.values("dep").annotate(avg=AVG("salary"))
筛选出部门 annoteta是按前面的内容分组
# 查询每一个作者的名字以及出版书籍的最高价格
Author.objects.annotate(max_price=Max("book__price")).values("name","max_price")
# 查询96年以后出生的每一个作者的名字以及出版书籍的最高价格
Author.objects.filter(birthday__year__gt=1996).annotate(max_price=Max("book__price")).values("name","max_price")
# 查询不止一个作者的书籍名称以及关联的作者个数
Book.objects.all().annotate(c=Count("authors")).filter(c__gt=1).values("title","c")
# 查询部门1的每一个销售的名字以及今天对应的成单量
Userinfo.objects.filter(depart_id=1).filter(customer__deal_date=now).annotate(c=Count("customers")).values("name","c")
统计每一本书的作者个数
ret=Book.objects.annotate(authorsNum=Count('authors__name')
F
Book.objects.filter(commnetNum__lt=F('keepNum')) #查评论数小于keepNum的
Book.objects.all().update(price=F("price")+30) #所有书的价格加30
Q: 查询条件or的关系
用|分割不同的Q查询条件,
查询作者名称是max或ding的书
bookList=Book.objects.filter(Q(authors__name="max")|Q(authors__name="ding"))
Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询
bookList=Book.objects.filter(Q(authors__name="max") & ~Q(publishDate__year=2017)).values_list("title")
Q 对象,它必须位于所有关键字参数的前面。
Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017),title__icontains="python")
2种查询方式
1. 基于对象查询 对应sql的子查询
正向: 按字段查
book_obj.authors.all()
反向: 小写表名_set/related_name
author_obj.book_set.all()
2. 基于双下划线查询 对应sql的join连表查询
正向: 按字段
Book.objects.filter(title="python").values("publish__name") #查python的出版社名称
反向: 按小写表名
Author.objects.filter(name__startswith="a").values("book__title") #查姓名是a开头的作者有哪些书
中介模型:
M2M类型自动生成第三张表,但是第三张不可修改, 如果想修改第三张表例如添加字段怎么办? 用中介模型, 既可以自定义第三张表字段 也可以继续使用orm的语法.
class Student(models.Model): name = models.CharField( max_length=32) courses=models.ManyToManyField("Courses",through="Score") # 告诉djaong用Source表做第三张表 class Course(models.Model): name = models.CharField( max_length=32) class Score(models.Model): student=models.ForeignKey("Student") course=models.ForeignKey("Course") score=models.IntegerField()
使用ORM步骤:
step1 定义模型类:
class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32,verbose_name="书籍名称") # CharField需要max_length参数来指定VARCHAR数据库字段的大小 state=models.BooleanField() pub_date=models.DateField() price=models.DecimalField(max_digits=8,decimal_places=2) publish=models.CharField(max_length=32) def __str__(self): return self.title class Meta: app_label="APP01" db_table="appBook" # 自定义表名,默认显示app_小写类名 unique_together=["title","price"] #设置联合唯一 verbose_name="书籍" #设置admin中表显示名称 ordering=["price"] #设置这个表以price字段排序
模型类常用字段:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<1> CharField 字符串字段, 用于较短的字符串. <2> IntegerField 用于保存整数. <3> FloatField 浮点数. 必须提供两个参数max_digits总位数 和decimal_places小数位数: e.gmodels.FloatField(..., max_digits=5, decimal_places=2) <4> AutoField:自增 整型 系统会自动添加一个名为id的自增的整型主键字段到你的 model. 默认名为id,可以修改名称:自定义一个主键:my_id=models.AutoField(primary_key=True) <5> BooleanField A true/false field. admin 用 checkbox 来表示此类字段. <6> TextField 一个容量很大的文本字段. admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框). <7> EmailField 一个带有检查Email合法性的 CharField,不接受 maxlength 参数. <8> DateField 一个日期字段. 共有下列额外的可选参数: Argument 描述 auto_now 每次修改时自动修改为当前时间. 通常用于表示 "last-modified" 时间戳. auto_now_add 对象创建时自动添加到当前时间 (仅仅在admin中有意义...) <9> DateTimeField 一个日期时间字段. 类似 DateField 支持同样的附加选项. <10> ImageField 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field, 如果提供这两个参数,则图片将按提供的高度和宽度规格保存. 字段的参数: (1)null 默认为False。 null=True 该字段不必填,是数据库的限制. blank 默认为False。 blank=True admin中不必填,是admin的限制. 通常null=True和blank=True一起设置 要注意,blank与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 (2)default 字段默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。 (3)primary_key 如果为True,那么这个字段就是模型的主键。如果没指定字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。 (4)unique 设置唯一,例如订单号设置为unique 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 (5)choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是下拉框,下拉框的选项就是choices 中的选项。
step2.在settings中配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'bms', # 要连接的数据库,连接前需要创建好
'USER':'root', # 连接数据库的用户名
'PASSWORD':'', # 连接数据库的密码
'HOST':'127.0.0.1', # 连接主机,默认本级
'PORT':3306 # 端口 默认3306
},
'app01': { #指定app01的配置,没有指定用default
'ENGINE': 'django.db.backends.mysql',
'NAME':'bms', # 要连接的数据库,连接前需要创建好
'USER':'root', # 连接数据库的用户名
'PASSWORD':'', # 连接数据库的密码
'HOST':'127.0.0.1', # 连接主机,默认本级
'PORT':3306 # 端口 默认3306
},
}
step3 项目名文件下的__init__,在里面写入:
import pymysql pymysql.install_as_MySQLdb() # 因为django默认驱动是MySQLdb,可是MySQLdb 对于py3支持不好,所以我们需要的驱动是PyMySQL.
step4 通过迁移的命令创建数据表:
python manage.py makemigrations
python manage.py migrate
step5 如果想打印orm转换过程中的sql,在settings中配置:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
添加记录举例:
#方法1,模型类的create book_obj=Book.objects.create(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12") #方法2,创建类对象再save() book_obj=Book(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12") book_obj.save()