您好,登錄后才能下訂單哦!
一.ORM
ORM:Object Relational Mapping(關系對象映射)
我們通過寫的類來表示數據庫中的表;
我們根據這個類創建的對象是數據庫表里的一行數據;
作用:為了實現面向對象的編程語言里不同類型系統的數據之間進行轉換,即:用面向對象的方式去操作數據庫進行創建表及增刪改查等操作;
好處:1.ORM使得我們通用的數據庫進行交互是變得簡單易行,而且完全不用考慮不同的SQL語句。能夠快速開發;2.可以避免一些對數據庫操作不熟帶來的由于手寫sql語句帶來的性能問題;
二.Django不能數據庫的使用
1.django默認使用sqlite數據庫驅動引擎(不用進行任何配置),如果要使用MySQL數據庫,則需要修改ettings.py中的DATABASES;
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文件增加配置文件
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的方式:
import pymysql
pymysql.install_as_MySQLdb()
三.表的創建
A.首先在項目的setting文件中設置DATABASES的參數(數據庫參數配置);
B.如果是非sqlite數據庫,則需要在對應的app應用下導入對應的數據庫模塊;
C.在對應APP應用下的model下添加需要創建表對應的classs;
1.單表的創建
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)
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:
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緩存。
十.歡迎關注作者公眾號
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。