一.ORM
ORM:Object Relational Mapping(关系对象映射)
咱们经过写的类来表示数据库中的表;
咱们根据这个类建立的对象是数据库表里的一行数据;
做用:为了实现面向对象的编程语言里不一样类型系统的数据之间进行转换,即:用面向对象的方式去操做数据库进行建立表及增删改查等操做;
好处:1.ORM使得咱们通用的数据库进行交互是变得简单易行,并且彻底不用考虑不一样的SQL语句。可以快速开发;2.能够避免一些对数据库操做不熟带来的因为手写sql语句带来的性能问题;
二.Django不能数据库的使用
1.django默认使用sqlite数据库驱动引擎(不用进行任何配置),若是要使用MySQL数据库,则须要修改ettings.py中的DATABASES;python
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'day70', 'USER': 'eric', 'PASSWORD': '123123', 'HOST': '192.168.182.128', 'PORT': '3306', } }
2.若查看orm操做执行的原生SQL语句,在project中的settings.py文件增长配置文件mysql
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
3.修改project 中的initpy 文件设置 Django默认链接MySQL的方式:git
import pymysql pymysql.install_as_MySQLdb()
三.表的建立
A.首先在项目的setting文件中设置DATABASES的参数(数据库参数配置);
B.若是是非sqlite数据库,则须要在对应的app应用下导入对应的数据库模块;
C.在对应APP应用下的model下添加须要建立表对应的classs;
1.单表的建立sql
class Userinfo(models.Model): username = models.CharField(max_length=256,primary_key=True) password = models.CharField(max_length=256) address = models.CharField(max_length=256) age = models.IntegerField()
2.一对多表的建立数据库
class Book(models.Model): # 从表 title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True) pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE)
class Publish(models.Model): # 主表 name=models.CharField(max_length=32) email=models.CharField(max_length=32) addr=models.CharField(max_length=32)
3.多对多表的建立
3.1方式1:使用ManyToManyField()方法进行关联多对多(此时在django中会自动生成第三张表book_author)django
from django.db import models # Create your models here. class Book(models.Model): # 从表 title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True)# 999999.99 pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) #建立Book和Authors的多对多关系 authors = models.ManyToManyField("Authors") class Publish(models.Model): # 主表 name=models.CharField(max_length=32) email=models.CharField(max_length=32) addr=models.CharField(max_length=32) class Authors(models.Model): name = models.CharField(max_length=64) age = models.IntegerField() sex = models.CharField(max_length=32)
3.2方式2:不使用ManyToManyField()方法,手动建立第三张book_author关联的表(一对多的关系)编程
from django.db import models # Create your models here. class Book(models.Model): # 从表 title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True)# 999999.99 pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) #手动建立第三张关联Book和Author的表Book_Author(此时ManyToManyField()不能再用) class Book_Author(models.Model): bookid = models.ForeignKey("Book",on_delete=models.CASCADE) authors = models.ForeignKey("Authors",on_delete=models.CASCADE) class Publish(models.Model): # 主表 name=models.CharField(max_length=32) email=models.CharField(max_length=32) addr=models.CharField(max_length=32) class Authors(models.Model): name = models.CharField(max_length=64) age = models.IntegerField() sex = models.CharField(max_length=32)
四.单表数据库增删改查
2.1增:向数据库中添加数据
方式1.使用model中的对象并结合object的create方法Userinfo.objects.create(username ='username',password = 'password',address = 'address',age = 34)
方式2.使用model中的类进行实例化进行操做
该方法是先使用model类进行实例化,再使用save进行保存缓存
user = Userinfo(username = 'username',password = 'password',address = 'address',age = 'age') user.save()
2.2删:删除数据库中的数据(先使用filter进行查询再删除)Userinfo.objects.filter(username=username).delete()
2.3改:修改数据库中现有的数据(先使用filter进行查询再进行修改)
方式1:app
Userinfo.objects.filter(username=username).update(password="password",address = "address") Sql:update tablename set password="password",address = "address" where username=username
方式2:编程语言
User = Userinfo.objects.filter(username=username) User.password="password" User.address ="address" User.save() Sql:update tablename set password="password",address = "address",age = "age" where username=username
方式1与方式2的区别:
方式1只修改指定的字段值,而方式2会修改全部字段的值(指定了新值则使用新值,没有新值则使用原有的值);方式2操做更复杂且效率低;
2.3查:按照条件查询数据库
A.判断查询结果是否有值(结果为布尔值,查询结果又记录返回Ture,不然返回False)Userinfo.objects.filter(username=request.POST.get('username')).exists()
B.查询某个表的全部记录Userinfo.objects.all()
C.查询某个表结果的N条记录
Userinfo.objects.all()[0] Userinfo.objects.all()[:] Userinfo.objects.all()[:4] Userinfo.objects.all()[: : 1] Userinfo.objects.all()[:4: -1] Userinfo.objects.first()--获取查询结果第1条,结果为实例对象 Userinfo.objects.laset()--获取查询结果最后1条,结果为实例对象
D.查询字段值等于某个值(=)
Userinfo.objects.filter(username=username)
E.查询字段值不等于某个值(!=)
Userinfo.objects.exclude(username='admin1')
F.查询字段值包含某些值(in)
Userinfo.objects.filter(age__in =[34,55,56]) Sql: select * from table where age in (34,55,56 )
G.查询字段值不包含某些值(not in)
Userinfo.objects.exclude(age__in =[34,55,56]) Sql: select * from table where age not in (34,55,56 )
H.查询字段值大于或大于等于某个值(>或>=)
Userinfo.objects.filter(age__gt =34) Sql: select * from table where age > 34; Userinfo.objects.filter(age__gte =34) Sql: select * from table where age >= 34;
I.查询字段值小于或小于等于某个值(<或<=)
Userinfo.objects.filter(age__lt =34) Sql: select * from table where age < 34; Userinfo.objects.filter(age__lte =34) Sql: select * from table where age <= 34;
J.查询字段值包含某个值(like)
1.不忽略大小写的模糊查询 like ‘%zh%’
Userinfo.objects.filter(username__contains ='zh')
2.忽略大小写的模糊查询 忽略大小写 like ‘%zh%’
Userinfo.objects.filter(username__icontains ='zh')
3.以...开头
Userinfo.objects.filter(username__startswith = 'z')
4.以...开头并忽略大小写
Userinfo.objects.filter(username__istartswith = 'z')
5.以...结尾
Userinfo.objects.filter(username__endswith ='g')
6.以...结尾并忽略大小写
Userinfo.objects.filter(username__iendswith ='g')
注:对于sqlite来讲,contains的做用效果等同于icontains
K.查询字段值不包含某个值(not like)
Userinfo.objects.exclude(username__contains = 'zh')
L.查询字段值在某个范围以内(between and)
方式1.Userinfo.objects.filter(age__gt = 30,age__lt = 60) 方式2.Userinfo.objects.filter(age__range = [34,56])(包含边界)
M.查询须要字段的结果
方式1: Userinfo.objects.filter(username=username).values("username","password","address","age") 获得的是一个QuerySet(字典类型)类型的list 方式2: Userinfo.objects.filter(username=username).values_list("username","password","address","age") 获得的是一个QuerySet(元组类型)类型的list
N.对查询结果去重
Userinfo.objects.filter(username__icontains='zh').distinct() Sql:select distinct * from tablename where username like 'zh';
O.对查询结果进行统计
Userinfo.objects.filter(username__icontains='zh').count() Sql:select count(*) from tablename where username like 'zh';
P.year 日期字段的年份
Q.month 日期字段的月份
R.day 日期字段的日
S.isnull=True/False
T.isnull=True 与 exact=None的区别
查询的另外一种方式:
Userinfo.objects.get(username = 'zhang')
只使用于有且只有一个条结果,不然将会报错。
经过filter()方法和get()方法查询的区别:
1.filter()的查询结果能够为任意状况(可有,可无,可惟一,可多条);而get()方法只适用于只有一条结果的状况;
2.filter()获得的查询结果为一个QuerySet的list,而get()方法获得的结果为一个实例化的对象(不能进行遍历)
users = Userinfo.objects.get(username = 'zhang') uame=users.username users = Userinfo.objects.all() uame2=users[0].username
五.一对多表的操做
A表中一条数据对应B表中N条数据,B表中已条数据只能对应A表中一条数据- - - -一对多;
多表操做也包含增删改查,主要与单表大体相同。注意一对多查询中的技巧便可。如下讲解查询的主要方法,也是多表操做中的重难点。
A.新增
方式1.直接给外键赋值对应的数值
新增
# 方式1.外键直接赋值数值
Book.objects.create(title = 'Javascript经典',price = 67.2,pub_date = '2017-12-02',publish_id =1)
方式2.给外键赋值对应的主键对象(django内部翻译对应的外键)
# 方式2.外键赋值对应的主键对象 publish = Publish.objects.get(name='清华出版社') Book.objects.create(title='python从入门到放弃', price=87.2, pub_date='2014-12-02', publish=publish)
B.查询
1.查看属性值
books = Book.objects.get(title=bookname) print("title=",books.title)
2.正向查询(经过从表外键属性查看主表的各个字段值)
books = Book.objects.get(title=bookname) print("publish=",books.publish) print("type=", type(books.publish)) print("publishname=",books.publish.name) #正向查询
如图:
3.经过从表的外键查询对应的主表的对应内容
#方式1.经过从表的外键值等于主表的主键进行关联 bookpublishs = Publish.objects.filter(id = Book.objects.get(title=bookname).publish_id) # 方式2.经过主表和从表的关联用从表的某一个字段来查询对应主表的信息 bookpublishs1 = Publish.objects.filter(book__title__icontains='入门')
*4.经过主表来查询对应从表的信息(确定多条结果)重点**
# 方式1.经过主表的主键与从表的外键相等的属性进行关联查询(复杂) books = Book.objects.filter(publish_id=Publish.objects.get(name=publishname).id) #方式2.经过从表外键属性来查询出对应主表主键对应的从表全部信息(即:查找出某出版社全部书籍的信息)(推荐使用) books = Book.objects.filter(publish =Publish.objects.get(name = publishname)) # 方式3.经过主表查询全部对应从表的记录(obj_set关键字,推荐使用) publish = Publish.objects.get(name = publishname) books = publish.book_set.all() #方式4.经过从表的外键之万能双下划线(__)进行关联主表查询 books1 = Book.objects.filter(publish__name=publishname) # 方式5.经过主表和从表的关联用从表对象的万能双下划线(__)进行关联从表进行查询 booknames = Publish.objects.filter(name='南方出版社').values('book__title','book__price')
六.多对多表的操做
A.方式1(ManyToManyField()方法)关联
from django.db import models # Create your models here. class Book(models.Model): # 从表 title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True)# 999999.99 pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) #建立Book和Authors的多对多关系 authors = models.ManyToManyField("Authors") class Publish(models.Model): # 主表 name=models.CharField(max_length=32) email=models.CharField(max_length=32) addr=models.CharField(max_length=32) class Authors(models.Model): name = models.CharField(max_length=64) age = models.IntegerField() sex = models.CharField(max_length=32)
新增:
#新增Book和Authors之间的关联,即:新增第三张关联表的记录 #找到须要进行关联的book(进行关联时必须是一条记录) book_obj = Book.objects.filter(title__contains='经典')[0] # 找到book须要进行关联的authors author_objs = Authors.objects.filter(age__lt=56) author_obj = Authors.objects.get(id=1) #获得一条记录 #将book和authors进行关联 book_obj.authors.add(*author_objs)#author_obj获得的是一个相似列表的集合,因此此处要在前面加*;若是获得的是一条记录则不用加* book_obj.authors.add(author_obj)
查询:
#经过book查询authors book = Book.objects.filter(id=1).all()[0] authors = book.authors.all() for i in range(len(authors)): print("book",authors[i].name,authors[i].age) # 经过authors查询book auth = Authors.objects.filter(id=1).all()[0] book = auth.book_set.all() for i in range(len(book)): print("book",book[i].title,book[i].publish) # 查询'再遇未知的本身'书的做者 info =Authors.objects.filter(book__title='再遇未知的本身').values('name','age','book__title','book__price')
删除:
#同理,解除book和authors之间的关联 # 找到须要进行关联的book(进行关联时必须是一条记录) book_obj = Book.objects.filter(title__contains='经典')[0] # 找到book须要进行关联的authors author_objs = Authors.objects.filter(age__lt=56) author_obj = Authors.objects.get(id=1) # 获得一条记录 #解除book和authors之间的关联 book_obj.authors.remove(author_obj) #解除一条关联的记录(不带*) book_obj.authors.remove(*author_objs) #解除多条关联的记录(带*) book_obj.authors.remove(3) #解除一条关联的记录(authors_id = 3)
修改:
参考一对多表的修改操做
B.手动建立第三张关联表(Book_Author)进行关联(*不推荐使用)
说明:不推荐该种方式,由于经过手动建立第三张关联的表,将不会在Book表中建立author的实例属性,不能直接使用万能的’__’方式来经过book调用author的相关属性,不方便操做。
from django.db import models # Create your models here. class Book(models.Model): # 从表 title=models.CharField(max_length=32,unique=True) price=models.DecimalField(max_digits=8,decimal_places=2,null=True)# 999999.99 pub_date=models.DateField() publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) #建立Book和Authors的多对多关系 # authors = models.ManyToManyField("Authors") #手动建立第三张关联Book和Author的表Book_Author(此时ManyToManyField()不能再用) class Book_Author(models.Model): book = models.ForeignKey("Book",on_delete=models.CASCADE) authors = models.ForeignKey("Authors",on_delete=models.CASCADE) class Publish(models.Model): # 主表 name=models.CharField(max_length=32) email=models.CharField(max_length=32) addr=models.CharField(max_length=32) class Authors(models.Model): name = models.CharField(max_length=64) age = models.IntegerField() sex = models.CharField(max_length=32)
新增:
Book_Author.objects.create(book_id = 1,authors_id=2)
查询:
#查询 #查询'再遇未知的本身'书的做者 #方式1: book = Book.objects.get(title='再遇未知的本身') authors = book.book_author_set.all().values('authors__name') # print("authors=",authors[0]['authors__name']) # 方式2: authors = book.book_author_set.all()[0].authors.name #查询'刘汉英'出过的书 authors = Authors.objects.get(name='刘汉英') book = authors.book_author_set.all().values('book__title','book__price')
修改:
删除:
七.model数据库的聚合函数及分组函数的使用方法
聚合函数包含:Sum() Max() Min() Avg() Count()......
分组函数: group by
Django中聚合函数的格式:
Book.objects.all().aggregate(自定义别名 = 聚合函数名称("字段名称"))
例如:
price = Book.objects.all().aggregate(Avg("price")) sum = Book.objects.all().aggregate(Sum("price")) count = Book.objects.all().aggregate(Count("price")) max = Book.objects.all().aggregate(Max("price")) min = Book.objects.all().aggregate(Min("price")) price = Book.objects.filter(authors__name='刘汉英').aggregate(Avg("price"))
Django中分组函数的格式:
Book.objects.all().values("分组的字段").annotate(分组后须要查询的内容)
例如:
#查询全部做者所写书籍的总数/平均价格/总和 res = Book.objects.all().values("authors__name").annotate(Avg("price"),Count("price"),Sum("price")) # print('res==',res) # 查询全部做者所写书籍中价格大于50元的总数/平均价格/总和 res = Book.objects.filter(price__gt = 50).values("authors__name").annotate(Avg("price"), Count("price"), Sum("price")) # print('res==', res) #查询各个出版社最便宜书的价格 #错误写法:若是以book进行查询,则查询的结果会以书为主体,则当出版社未出版书时结果不显示出来(由于是以书为主体,而不是以出版社为主体的) res = Book.objects.all().values("publish__name").annotate(Min("price")) print("res=",res) print('---'*20) #正确写法,以publish为主体进行分组查询 res = Publish.objects.all().values('name').annotate(minprice = Min("book__price")) #minprice自定义别名 print("res=", res)
八.F查询和Q查询
当咱们须要把全部书籍的价格提升10元时,又该怎么操做呢?在sql中应该为:update book set price = (price+10)
此时咱们能够考虑使用django中的F()函数
做用:操做数据表中的某列值,F()容许Django在未实际连接数据的状况下具备对数据库字段的值的引用,不用获取对象放在内存中再对字段进行操做,直接执行原生产sql语句操做。一般状况下咱们在更新数据时须要先从数据库里将原数据取出后方在内存里,而后编辑某些属性,最后提交。
#修改全部书籍的价格使其加价10元 Book.objects.all().update(price=F("price")+10)
在上面的全部场景中,咱们在进行查询时的过滤条件(filter()函数))只使用了单条件或者多条件(and)查询,没法使用or 或者not进行查询。此时django提供了Q()函数来完成or 或 not功能。
做用:对对象进行复杂查询,并支持&(and),|(or),~(not)操做符。
#Q查询和关键字查询并用,注意此时必须Q()放在关键字前面,不然报错 #查询全部南方出版社出版且价格大于50的书籍 book1 = Book.objects.filter(Q(publish__name='南方出版社'),price__lt=50) print("book1=",book1) book2 = Book.objects.filter(price__lt=50,publish__name='南方出版社') print('book2=',book2)
# 查询全部南方出版社出版或者价格大于100的书籍 book3 = Book.objects.filter(Q(publish__name='南方出版社')| Q(price__gt=100)).values("title")
# 查询全部南方出版社出版或者价格不大于100的书籍 book4 = Book.objects.filter(Q(publish__name='南方出版社')|Q(price__lte=100)).values("title") print('book4=', book4) book5 = Book.objects.filter(Q(publish__name='南方出版社') | ~Q(price__gt=100)).values("title") print('book5=', book5)
九.QuerySet集合对象的特殊属性
1.不使用QuerySet时不进行查询数据库操做
2.同一个QuerySet,django有缓存不会重复操做数据库,直接读取缓存;若是中间修改了后面须要使用则应该从新查询获取QuerySet
QuerySet的特性:
1.可切片
2.可迭代性
可迭代性说明:django的QuerySet自带cache机制(缓存机制),它会把一次性查出的结果都放进缓存中,当数据量极大时会致使内存被极大的消耗,此时会严重影响性能。此时,咱们能够考虑使用python的迭代器iterator()进行处理,这里每次只存储部分少许须要使用的数据在内存中,经过next()方法进行获取下次须要的数据。这样既能够知足需求,又能够节省内存。可是,使用iterator()并不会生成QuerySet缓存,可能会须要额外的查询数据库。exists()也是不会生成QuerySet缓存。
十.欢迎关注做者公众号