orm
1. 配置环境
-
在项目的setting中配置数据库的相关信息
DATABASES = { 'default':{ 'ENGINE':'...mysql', 'NAME':'库名', 'HOST':'127.0.0.1', 'PORT':3306, 'USER':'root', 'PASSWORD':'123' } }
-
在项目的init文件中配置
import pymysql pymysql.install_as_MySQLdb()
-
创建表
- 创建完项目后,我们进入
app
,进入models.py
创建我们的模型(数据库)- (注意) 期中id为自增字段并且为主键(如果不写主键字段默认id为主键字段)
- 创建完项目后,我们进入
-
数据库同步指令(在terminal中输入以下命令)
#创建一个记录告诉Django我要创建一个表 python manage.py makemigrations #执行上一个记录 ptthon manage.py migrate
2. 用orm进行(简单的)增删改查
增(create)
-
#实例化要添加的记录(对象) student_obj = models.Student( name='dazhaung', age=23, ) #存储到数据库 student_obj.save()
-
#期中参数也可以写成 **{'name':'xx','age':6} 的格式 new_obj = models.Student.objects.create(name='xiaozhuang2',age=6) #点属性,可以获取对应字段的数据 print(new_obj.name) print(new_obj.age)
-
#进行批量创建 objs_list = [] for i in range(100,3000000): obj = models.Student( name='xiangxixxx', age = 10, ) objs_list.append(obj) #先存到内存,最后只进行一次磁盘io models.Student.objects.bulk_create(objs_list)
-
#有就更新,没有就创建 models.Student.objects.update_or_create( #先找到对应的字段 name='红旭妹妹2', #进行更新或增加 defaults={ 'age':38, } )
删(delete)
-
#delete queryset 和model对象都可以调用 #model对象来调用的delete方法 models.Student.objects.get(id=3).delete() #queryset对象来调用的delete方法 models.Student.objects.filter(name='红旭妹妹').delete() #删除所有 models.Student.objects.all().delete()
改(update)
-
#update方法 只能queryset对象能调用更新方法 models.Student.objects.filter(name='红旭妹妹').update(age=38)
查(filter)
-
查询所有的数据(.all())
-
#返回queryset对象 all_objs = models.Student.objects.all()
-
-
条件查询 (.filter())
-
#返回queryset对象 #查询不到内容,不会 报错,返回一个<QuerySet []>空的queryset objs = models.Student.objects.filter(id=2)
-
-
条件查询(.get())
-
#返回model对象 #而且get方法有且必须只有1个结果否者报错 obj = models.Student.objects.get(id=3)
-
3. 查询接口
all():
1. 查询所有结果,结果是queryset类型
filter(**kwargs):
-
它包含了与所给筛选条件相匹配的对象,结果也是queryset类型
-
期中多个参数之间用逗号隔开是and的关系
Book.objects.filter(title='linux',price=100)
-
queryset类型可以调用fitler在过滤
models.Student.objects.all().filter(id=7)
get(**kwargs):
-
返回model对象类型
-
get方法有且必须只有1个结果否者报错
Book.objects.get(id=1)
exclude(**kwargs):
-
排除的意思
-
它包含了与所给筛选条件不匹配的对象
-
返回值是queryset类型
#返回id不等于6的所有的对象 Book.objects.exclude(id=6) #在queryset基础上调用 Book.objects.all().exclude(id=6)
order_by(*field):
-
对查询结果排序
-
queryset类型的数据来调用
-
默认是按照id来升序排列的
-
返回值还是queryset类型
#直接写price,默认是按照price升序排列 #多条件排序,按照price进行升序,price相同的数据,按照id进行升序 models.Book.objects.all().order_by('price','id') #按照字段降序排列,就写个负号就行了order_by('-price')
reverse():
-
对查询结果反向排序
-
queryset类型的数据来调用
-
返回值还是queryset类型
query = models.Student.objects.all().order_by('id').reverse()
count():
- queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
first():
-
queryset类型的数据来调用,返回第一条记录
Book.objects.all()[0] = Book.objects.all().first()
-
得到的是model对象
last():
- 同上----返回最后一条记录
exists():
-
queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False。
#翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据 all_books = models.Book.objects.all().exists()
values(*field):
- queryset类型的数据来调用
- 返回一个ValueQuerySet——一个特殊的QuerySet(可迭代的字典序列)
values_list(*field):
- 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
distinct():
-
values和values_list得到的queryset类型的数据来调用
-
从返回结果中剔除重复纪录,结果还是queryset
query = models.Student.objects.all().values('age').distinct()
总结:
接口名 | 作用 | 调用类型 | 结果类型 |
---|---|---|---|
all() |
查询所有结果 | objects | QuerySet |
filter |
条件查询 | objects | QuerySet |
get |
条件查询,但只返回一条数据 | objects | Model(行记录对象) |
exclude |
匹配非条件的对象 | objects | QuerySet |
order_by |
对查询结果进行排序 | QuerySet | QuerySet |
reverse |
对查询结果反向排序 | QuerySet | QuerySet |
count |
返回匹配查询的对象数量 | QuerySet | int |
first |
返回第一条记录 | QuerySet | Model |
last |
返回最后一条记录 | QuerySet | Model |
exists |
判断QuerySet是否包含数据 | QuerySet | bool(True、False) |
values |
以字典方式返回 | QuerySet | ValueQuerySet |
values_list |
以元组方式返回 | QuerySet | dic |
distinct |
去重 | values和values_list得到的queryset类型 | queryset |
4.模糊查询
#price值等于这三个里面的任意一个的对象
Book.objects.filter(price__in=[100,200,300])
#大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__gt=100)
#小于,小于等于是price__lte=100
Book.objects.filter(price__lt=100)
#sql的between and,大于等于100,小于等于200
Book.objects.filter(price__range=[100,200])
#title值中包含python的
Book.objects.filter(title__contains="python")
#title值中包含python的---不区分大小写
Book.objects.filter(title__icontains="python")
#以什么开头,istartswith 不区分大小写
Book.objects.filter(title__startswith="py")
#找2012年的所有书籍
Book.objects.filter(pub_date__year=2012)
#找大于2012年的所有书籍
models.Book.objects.filter(pub_date__year__gt=2012)
总结:
模糊查找类型 | 表示方法 |
---|---|
任意包含某个值 | xx__in=[100,200,300 |
大于某个值 | xx__gt=100 |
小于某个值 | xx_lt=100 |
介于某个值之间 | xx_range=[100,200] |
包含某个字符 | xx_contains=‘python’ |
不区分大小写 | xx_icontains=‘python’ |
以什么开头 | xx_startswith=‘py’ |
查询某一年 | xx_year=2012 |
大于某一年 | xx_year_gt=2012 |
5. 外部文件操作django的models
#外部文件使用django的models,需要配置django环境
import os
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "singletablehw.settings")
import django
django.setup()
from app01 import models
import datetime
#批量创建
obj_list = []
for i in range(1,10):
obj = models.Book(
title='葵花宝典第%s式'%i,
price=20 + i,
pub_date='198%s-11-11 00:00:00'%i,
# pub_date=datetime.datetime.now(),
publish= '吴老板出版社' if i < 5 else '太白出版社',
)
obj_list.append(obj)
models.Book.objects.bulk_create(obj_list)
6. url反向解析
url中:
#name='abook' 别名
url(r'^add_book/', views.add_book,name='abook'),
#name=‘delete_book’ 有一个数字参数
url(r'^delete_book/(\d+)/', views.delele_book,name='delete_book'),
视图中:
from django.urls import reverse
reverse('abook') ---代表解析了无参数的别名
#/delete_book/71/ 带参数的
reverse('delete_book',args=(71,))
模板
{
% url 'abook' %} 无参数的
{
% url 'delete_book' book.id %} 无参数的
7. 一对一,一对多,多对多关系
1. 创建表
-
一对一
-
#to_field可以不写,默认是关联到另一张表的主键 #on_delete=models.CASCADE------进行级联删除 xx = models.OneToOneField(to='表名',to_field='字段名',on_delete=models.CASCADE)
-
例子:
#一对一到AuthorDetail表 生成为表字段之后,数据库会自动变为authorDetail_id这样有一个名称 authorDetail=models.OneToOneField(to='AuthorDetail')
-
-
一对多
-
xx = models.ForeignKey(to='表名',to_field='字段名',on_delete=models.CASCADE)
-
例子:
#数据库会自动变为publishs_id这样有一个名称 publishs=models.ForeignKey(to="Publish")
-
-
多对多
-
xx = models.ManyToManyField(to='另外一个表名') #这是自动创建第三表
-
例子:
authors=models.ManyToManyField(to='Author',) #手动创建第三张表,暂时忽略 # class BookToAuthor(models.Model): # book_id = models.ForeignKey(to='Book') # author_id = models.ForeignKey(to='Author')
-
2. 增加数据
- 一对一
#方式1
new_author_detail = models.AuthorDetail.objects.create(
birthday='1979-08-08',
telephone='138383838',
addr='黑龙江哈尔滨'
)
models.Author.objects.create(
name='王涛',
age='40',
authorDetail=new_author_detail,
)
# 方式2 常用
obj = models.AuthorDetail.objects.filter(addr='山西临汾').first()
models.Author.objects.create(
name='王涛',
age='40',
authorDetail_id=obj.id,
- 一对多
#方式1
obj = models.Publish.objects.get(id=2)
models.Book.objects.create(
title = '李帅的床头故事',
publishDate='2019-07-22',
price=3,
# publishs=models.Publish.objects.get(id=1),
publishs=obj,
)
# 方式2 常用
obj = models.Publish.objects.get(id=2)
models.Book.objects.create(
title='李帅的床头故事2',
publishDate='2019-07-21',
price=3.5,
# publishs=models.Publish.objects.get(id=1),
#publishs_id为存到数据库的名字
publishs_id=obj.id
)
- 多对多
# 方式1 常用
#先寻找增加那个对象
book_obj = models.Book.objects.get(nid=1)
#add增加
book_obj.authors.add(*[1,2])
# 方式2
author1 = models.Author.objects.get(id=1)
author2 = models.Author.objects.get(id=3)
#第五本书是id为1 和id为3 的作者写的
book_obj = models.Book.objects.get(nid=5)
book_obj.authors.add(*[author1,author2])
3. 删除数据
-
一对一,一对多(是一样的删除方式)
# 表一外键关联到表二,表一删除,不影响表2,表2删除会影响表1 #一对一 # models.AuthorDetail.objects.get(id=2).delete() # models.Author.objects.get(id=3).delete() # 一对多 # models.Publish.objects.get(id=1).delete() # models.Book.objects.get(nid=1).delete()
-
多对多关系删除
#找到要删除的对象 book_obj = models.Book.objects.get(nid=6) #通过进行多对多联系的字段删除 book_obj.authors.remove(6) #删除多条数据 book_obj.authors.remove(*[5,6]) #清空book nid=6的数据 book_obj.authors.clear() book_obj.authors.add(*[1,]) #删除然后更新 book_obj.authors.set('1') book_obj.authors.set(['5','6'])
4. 更新数据
#一对一
models.Author.objects.filter(id=5).update(
name='崔老师',
age=16,
# authorDetail=models.AuthorDetail.objects.get(id=5),
authorDetail_id=4,
)
#一对多
models.Book.objects.filter(pk=4).update(
title='B哥的往事2',
# publishs=models.Publish.objects.get(id=3),
publishs_id=3,
)
5.(基于对象的跨表查询)
正向查询和反向查询(关系属性(字段)写在哪个类(表)里面,从当前类(表)的数据去查询它关联类(表)的数据叫做正向查询,反之叫做反向查询)
-
一对一
-
正向查询
-
正向查询靠对象,取到数据对象后,通过点操作符对外键操作,就能拿到外键的对象,从而取到内容
author_obj = models.Author.objects.filter(name='admin').first() result = author_obj.authorDetail.telephone
-
-
反向查询
-
查到对象后,通过小写的表名来获取另一个表的属性
author_detail_obj = models.AuthorDetail.objects.get(telephone='213') result = author_detail_obj.author.name
-
-
-
一对多
-
正向查询
-
与一对一较为类似
book_obj = models.Book.objects.get(title='第二本书') result = book_obj.publishs.name
-
-
反向查询
-
注意对象调用的是加
_set
的方法,然后all()
即可取出全部内容publish_obj = models.Publish.objects.get(name="老男人出版社") result = publish_obj.book_set.all()
-
-
-
多对多
-
正向查询
-
book_obj = models.Book.objects.get(title='第一本书') result = book_obj.authors.all()
-
-
反向查询
-
auth_obj = models.Author.objects.get(name='admin') result = auth_obj.book_set.all()
-
-
6. 基于双下划綫的跨表查询
-
一对一
- 正向查询
#obj为model对象 通过model对象的一对一对应的键 查看 其对应的键 obj = models.Author.objects.filter(name='崔老师').values('authorDetail__telephone')
- 反向查询
#values可以不写,则去除能拿到的全部数据。filter中的双下划线表示联表 result=models.AuthorDetail.objects.filter(author__name='admin').values('telephone')
-
一对多
-
正向查询
result = models.Book.objects.filter(title='第一本书').values("publishs__name")
-
反向查询
result = models.Publish.objects.filter(book__title='第一本书').values('name')
-
-
多对多
- 正向查询
obj = models.Book.objects.filter(publishs__name='老男人出版社').values('title')
- 反向查询
obj = models.Publish.objects.filter(name='老男人出版社').values("book__title")
7.进阶查询
- 查询老男人出版社出版的书的名字和作者的名字
#三表联查
obj = models.Book.objects.filter(publishs__name='老男人出版社').values('title','authors__name')
#'book__authors__name'是通过book表的外键进行查询
obj = models.Publish.objects.filter(name='老男人出版社').values('book__title','book__authors__name')
8.反向查询代理
- 在创建表是外键字段添加参数
related_name
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2) #decimal(16,2)
publishs=models.ForeignKey(to="Publish",related_name='xx')
authors=models.ManyToManyField(to='Author',)
9.聚合函数
from django.db.models import Avg,Max,Min,Sum,Count
# 计算所有图书的平均价格
obj = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price')) #aggregate()是QuerySet 的一个终止子句,得到的是个字典.
# print(obj['m'] - 2) #{'price__avg': 2.833333}
10.分组
-
models.Publish.objects.annotate(a=Avg('book__price')).values('a')
-
obj = models.Book.objects.values('publishs_id').annotate(a=Avg('price')) ## select avg (price) from app01_ book GROUP BY publishs_ id;
11.F和Q查询
-
F查询(针对自己表中的数据进行查询)
-
from django.db.models import F,Q #good和comment都是book的字段 models.Book.objects.filter(good__gt=F('comment')*2) #对一列price字段都加一 models.Book.objects.all().update(price=F('price')+1)
-
-
Q查询
-
# 与& 或| 非~ filter(Q(xx=11)|Q(ss=22)&Q(oo=33)) filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33)) &优先级高 filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33),name='dd')
-
bjects.annotate(a=Avg(‘book__price’)).values(‘a’)
2. ```python
obj = models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
## select avg (price) from app01_ book GROUP BY publishs_ id;
11.F和Q查询
-
F查询(针对自己表中的数据进行查询)
-
from django.db.models import F,Q #good和comment都是book的字段 models.Book.objects.filter(good__gt=F('comment')*2) #对一列price字段都加一 models.Book.objects.all().update(price=F('price')+1)
-
-
Q查询
-
# 与& 或| 非~ filter(Q(xx=11)|Q(ss=22)&Q(oo=33)) filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33)) &优先级高 filter(Q(Q(xx=11)|Q(ss=22))&Q(oo=33),name='dd')
-