django指定mysql數據庫 ORM查詢
django原生自帶數據庫,不過自帶的數據庫是sqlite
這次使用的orm框架操作數據庫
這時候你就需要換上你想用的數據庫比如大眾化的mysql
但是你還是首先要先安裝pymysql的驅動
pip install PyMySQL
在Django的工程同名子目錄的__init__.py文件中添加如下語句
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
django 在python2.7一直使用的是db操作數據庫
由於django比較戀舊所以給pymysql換個名而已
修改DATABASES配置信息
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.mysql‘,
‘HOST‘: ‘127.0.0.1‘, # 數據庫主機
‘PORT‘: 3306, # 數據庫端口
‘USER‘: ‘root‘, # 數據庫用戶名
‘PASSWORD‘: ‘mysql‘, # 數據庫用戶密碼
‘NAME‘: ‘django_demo‘ # 數據庫名字
}
}
記得建完表在指定數據庫的名字
- 模型類被定義在"應用/models.py"文件中。
- 模型類必須繼承自Model類,位於包django.db.models中。
接下來首先以"圖書-英雄"管理為例進行演示。
定義
創建應用booktest,在models.py 文件中定義模型類。
from django.db import models
#定義圖書模型類BookInfo
class BookInfo(models.Model):
btitle = models.CharField(max_length=20, verbose_name=‘名稱‘)
bpub_date = models.DateField(verbose_name=‘發布日期‘)
bread = models.IntegerField(default=0, verbose_name=‘閱讀量‘)
bcomment = models.IntegerField(default=0, verbose_name=‘評論量‘)
is_delete = models.BooleanField(default=False, verbose_name=‘邏輯刪除‘)
class Meta:
db_table = ‘tb_books‘ # 指明數據庫表名
verbose_name = ‘圖書‘ # 在admin站點中顯示的名稱
verbose_name_plural = verbose_name # 顯示的復數名稱
def __str__(self):
"""定義每個數據對象的顯示信息"""
return self.btitle
#定義英雄模型類HeroInfo
class HeroInfo(models.Model):
GENDER_CHOICES = (
(0, ‘male‘),
(1, ‘female‘)
)
hname = models.CharField(max_length=20, verbose_name=‘名稱‘)
hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name=‘性別‘)
hcomment = models.CharField(max_length=200, null=True, verbose_name=‘描述信息‘)
hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=‘圖書‘) # 外鍵
is_delete = models.BooleanField(default=False, verbose_name=‘邏輯刪除‘)
class Meta:
db_table = ‘tb_heros‘
verbose_name = ‘英雄‘
verbose_name_plural = verbose_name
def __str__(self):
return self.hname
字段類型
類型 | 說明 |
---|---|
AutoField | 自動增長的IntegerField,通常不用指定,不指定時Django會自動創建屬性名為id的自動增長屬性 |
BooleanField | 布爾字段,值為True或False |
NullBooleanField | 支持Null、True、False三種值 |
CharField | 字符串,參數max_length表示最大字符個數 |
TextField | 大文本字段,一般超過4000個字符時使用 |
IntegerField | 整數 |
DecimalField | 十進制浮點數, 參數max_digits表示總位數, 參數decimal_places表示小數位數 |
FloatField | 浮點數 |
DateField | 日期, 參數auto_now表示每次保存對象時,自動設置該字段為當前時間,用於"最後一次修改"的時間戳,它總是使用當前日期,默認為False; 參數auto_now_add表示當對象第一次被創建時自動設置當前時間,用於創建的時間戳,它總是使用當前日期,默認為False; 參數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤 |
TimeField | 時間,參數同DateField |
DateTimeField | 日期時間,參數同DateField |
FileField | 上傳文件字段 |
ImageField | 繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片 |
選項
選項 | 說明 |
---|---|
null | 如果為True,表示允許為空,默認值是False |
blank | 如果為True,則該字段允許為空白,默認值是False |
db_column | 字段的名稱,如果未指定,則使用屬性的名稱 |
db_index | 若值為True, 則在表中會為此字段創建索引,默認值是False |
default | 默認 |
primary_key | 若為True,則該字段會成為模型的主鍵字段,默認值是False,一般作為AutoField的選項使用 |
unique | 如果為True, 這個字段在表中必須有唯一值,默認值是False |
外鍵
在設置外鍵時,需要通過on_delete選項指明主表刪除數據時,對於外鍵引用表數據如何處理,在django.db.models中包含了可選常量:
-
CASCADE 級聯,刪除主表數據時連通一起刪除外鍵表中數據
-
PROTECT 保護,通過拋出ProtectedError異常,來阻止刪除主表中被外鍵應用的數據
-
SET_NULL 設置為NULL,僅在該字段null=True允許為null時可用
-
SET_DEFAULT 設置為默認值,僅在該字段設置了默認值時可用
-
from django.conf import settings from django.contrib.auth import get_user_model from django.db import models def get_sentinel_user(): return get_user_model().objects.get_or_create(username=‘deleted‘)[0] class MyModel(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), )
-
DO_NOTHING 不做任何操作,如果數據庫前置指明級聯性,此選項會拋出IntegrityError異常
添加測試數據
insert into tb_books(btitle,bpub_date,bread,bcomment,is_delete) values
(‘射雕英雄傳‘,‘1980-5-1‘,12,34,0),
(‘天龍八部‘,‘1986-7-24‘,36,40,0),
(‘笑傲江湖‘,‘1995-12-24‘,20,80,0),
(‘雪山飛狐‘,‘1987-11-11‘,58,24,0);
insert into tb_heros(hname,hgender,hbook_id,hcomment,is_delete) values
(‘郭靖‘,1,1,‘降龍十八掌‘,0),
(‘黃蓉‘,0,1,‘打狗棍法‘,0),
(‘黃藥師‘,1,1,‘彈指神通‘,0),
(‘歐陽鋒‘,1,1,‘蛤蟆功‘,0),
(‘梅超風‘,0,1,‘九陰白骨爪‘,0),
(‘喬峰‘,1,2,‘降龍十八掌‘,0),
(‘段譽‘,1,2,‘六脈神劍‘,0),
(‘虛竹‘,1,2,‘天山六陽掌‘,0),
(‘王語嫣‘,0,2,‘神仙姐姐‘,0),
(‘令狐沖‘,1,3,‘獨孤九劍‘,0),
(‘任盈盈‘,0,3,‘彈琴‘,0),
(‘嶽不群‘,1,3,‘華山劍法‘,0),
(‘東方不敗‘,0,3,‘葵花寶典‘,0),
(‘胡斐‘,1,4,‘胡家刀法‘,0),
(‘苗若蘭‘,0,4,‘黃衣‘,0),
(‘程靈素‘,0,4,‘醫術‘,0),
生成遷移文件
python manage.py makemigrations
同步到數據庫中
python manage.py migrate
比flask簡單不少..
shell工具
Django的manage工具提供了shell命令,幫助我們配置好當前工程的運行環境(如連接好數據庫等),以便可以直接在終端中執行測試python語句。
通過如下命令進入shell
python manage.py shell
查看MySQL數據庫日誌
查看mysql數據庫日誌可以查看對數據庫的操作記錄。 mysql日誌文件默認沒有產生,需要做如下配置:
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
tail -f /var/log/mysql/mysql.log # 可以實時查看數據庫的日誌內容
# 如提示需要sudo權限,執行
# sudo tail -f /var/log/mysql/mysql.log
數據庫操作—增、刪、改、查
1 增加
增加數據有兩種方法。
1)save
通過創建模型類對象,執行對象的save()方法保存到數據庫中。
>>> from datetime import date
>>> book = BookInfo(
btitle=‘西遊記‘,
bput_date=date(1988,1,1),
bread=10,
bcomment=10
)
>>> book.save()
>>> hero = HeroInfo(
hname=‘孫悟空‘,
hgender=0,
hbook=book
)
>>> hero.save()
>>> hero2 = HeroInfo(
hname=‘豬八戒‘,
hgender=0,
hbook_id=book.id
)
>>> hero2.save()
2)create
通過模型類.objects.create()保存。
>>> HeroInfo.objects.create(
hname=‘沙悟凈‘,
hgender=0,
hbook=book
)
<HeroInfo: 沙悟凈>
2 查詢
2.1 基本查詢
get 查詢單一結果,如果不存在會拋出模型類.DoesNotExist異常。
all 查詢多個結果。
count 查詢結果數量。
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 射雕英雄傳>, <BookInfo: 天龍八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飛狐>, <BookInfo: 西遊記>]>
>>> book = BookInfo.objects.get(btitle=‘西遊記‘)
>>> book.id
5
>>> BookInfo.objects.get(id=3)
<BookInfo: 笑傲江湖>
>>> BookInfo.objects.get(pk=3)
<BookInfo: 笑傲江湖>
>>> BookInfo.objects.get(id=100)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/query.py", line 380, in get
self.model._meta.object_name
db.models.DoesNotExist: BookInfo matching query does not exist.
>>> BookInfo.objects.count()
6
2.2 過濾查詢
實現SQL中的where功能,包括
- filter 過濾出多個結果
- exclude 排除掉符合條件剩下的結果
- get 過濾單一結果
對於過濾條件的使用,上述三個方法相同,故僅以filter進行講解。
過濾條件的表達語法如下:
屬性名稱__比較運算符=值
# 屬性名稱和比較運算符間使用兩個下劃線,所以屬性名不能包括多個下劃線
1)相等
exact:表示判等。
例:查詢編號為1的圖書。
BookInfo.objects.filter(id__exact=1)
可簡寫為:
BookInfo.objects.filter(id=1)
2)模糊查詢
contains:是否包含。
說明:如果要包含%無需轉義,直接寫即可。
例:查詢書名包含‘傳‘的圖書。
BookInfo.objects.filter(btitle__contains=‘傳‘)
startswith、endswith:以指定值開頭或結尾。
例:查詢書名以‘部‘結尾的圖書
BookInfo.objects.filter(btitle__endswith=‘部‘)
以上運算符都區分大小寫,在這些運算符前加上i表示不區分大小寫,如iexact、icontains、istartswith、iendswith.
3) 空查詢
isnull:是否為null。
例:查詢書名不為空的圖書。
BookInfo.objects.filter(btitle__isnull=False)
4) 範圍查詢
in:是否包含在範圍內。
例:查詢編號為1或3或5的圖書
BookInfo.objects.filter(id__in=[1, 3, 5])
5)比較查詢
- gt 大於 (greater then)
- gte 大於等於 (greater then equal)
- lt 小於 (less then)
- lte 小於等於 (less then equal)
例:查詢編號大於3的圖書
BookInfo.objects.filter(id__gt=3)
不等於的運算符,使用exclude()過濾器。
例:查詢編號不等於3的圖書
BookInfo.objects.exclude(id=3)
6)日期查詢
year、month、day、week_day、hour、minute、second:對日期時間類型的屬性進行運算。
例:查詢1980年發表的圖書。
BookInfo.objects.filter(bpub_date__year=1980)
例:查詢1980年1月1日後發表的圖書。
BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
F對象
之前的查詢都是對象的屬性與常量值比較,兩個屬性怎麽比較呢? 答:使用F對象,被定義在django.db.models中。
語法如下:
F(屬性名)
例:查詢閱讀量大於等於評論量的圖書。
from django.db.models import F
BookInfo.objects.filter(bread__gte=F(‘bcomment‘))
可以在F對象上使用算數運算。
例:查詢閱讀量大於2倍評論量的圖書。
BookInfo.objects.filter(bread__gt=F(‘bcomment‘) * 2)
Q對象
多個過濾器逐個調用表示邏輯與關系,同sql語句中where部分的and關鍵字。
例:查詢閱讀量大於20,並且編號小於3的圖書。
BookInfo.objects.filter(bread__gt=20,id__lt=3)
或
BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)
如果需要實現邏輯或or的查詢,需要使用Q()對象結合|運算符,Q對象被義在django.db.models中。
語法如下:
Q(屬性名__運算符=值)
例:查詢閱讀量大於20的圖書,改寫為Q對象如下。
from django.db.models import Q
BookInfo.objects.filter(Q(bread__gt=20))
Q對象可以使用&、|連接,&表示邏輯與,|表示邏輯或。
例:查詢閱讀量大於20,或編號小於3的圖書,只能使用Q對象實現
BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))
Q對象前可以使用~操作符,表示非not。
例:查詢編號不等於3的圖書。
BookInfo.objects.filter(~Q(pk=3))
聚合函數
使用aggregate()過濾器調用聚合函數。聚合函數包括:Avg 平均,Count 數量,Max 最大,Min 最小,Sum 求和,被定義在django.db.models中。
例:查詢圖書的總閱讀量。
from django.db.models import Sum
BookInfo.objects.aggregate(Sum(‘bread‘))
註意aggregate的返回值是一個字典類型,格式如下:
{‘屬性名__聚合類小寫‘:值}
如:{‘bread__sum‘:3}
使用count時一般不使用aggregate()過濾器。
例:查詢圖書總數。
BookInfo.objects.count()
註意count函數的返回值是一個數字。
2.3 排序
使用order_by對結果進行排序
BookInfo.objects.all().order_by(‘bread‘) # 升序
BookInfo.objects.all().order_by(‘-bread‘) # 降序
2.4 關聯查詢
由一到多的訪問語法:
一對應的模型類對象.多對應的模型類名小寫_set 例:
b = BookInfo.objects.get(id=1)
b.heroinfo_set.all()
由多到一的訪問語法:
多對應的模型類對象.多對應的模型類中的關系類屬性名 例:
h = HeroInfo.objects.get(id=1)
h.hbook
訪問一對應的模型類關聯對象的id語法:
多對應的模型類對象.關聯類屬性_id
例:
h = HeroInfo.objects.get(id=1)
h.hbook_id
關聯過濾查詢
由多模型類條件查詢一模型類數據:
語法如下:
關聯模型類名小寫__屬性名__條件運算符=值
註意:如果沒有"__運算符"部分,表示等於。
例:
查詢圖書,要求圖書英雄為"孫悟空"
BookInfo.objects.filter(heroinfo__hname=‘孫悟空‘)
查詢圖書,要求圖書中英雄的描述包含"八"
BookInfo.objects.filter(heroinfo__hcomment__contains=‘八‘)
由一模型類條件查詢多模型類數據:
語法如下:
一模型類關聯屬性名__一模型類屬性名__條件運算符=值
註意:如果沒有"__運算符"部分,表示等於。
例:
查詢書名為“天龍八部”的所有英雄。
HeroInfo.objects.filter(hbook__btitle=‘天龍八部‘)
查詢圖書閱讀量大於30的所有英雄
HeroInfo.objects.filter(hbook__bread__gt=30)
3 修改
修改更新有兩種方法
1)save
修改模型類對象的屬性,然後執行save()方法
hero = HeroInfo.objects.get(hname=‘豬八戒‘)
hero.hname = ‘豬悟能‘
hero.save()
2)update
使用模型類.objects.filter().update(),會返回受影響的行數
HeroInfo.objects.filter(hname=‘沙悟凈‘).update(hname=‘沙僧‘)
4 刪除
刪除有兩種方法
1)模型類對象delete
hero = HeroInfo.objects.get(id=13)
hero.delete()
2)模型類.objects.filter().delete()
HeroInfo.objects.filter(id=14).delete()
查詢集 QuerySet
1 概念
Django的ORM中存在查詢集的概念。
查詢集,也稱查詢結果集、QuerySet,表示從數據庫中獲取的對象集合。
當調用如下過濾器方法時,Django會返回查詢集(而不是簡單的列表):
- all():返回所有數據。
- filter():返回滿足條件的數據。
- exclude():返回滿足條件之外的數據。
- order_by():對結果進行排序。
對查詢集可以再次調用過濾器進行過濾,如
BookInfo.objects.filter(bread__gt=30).order_by(‘bpub_date‘)
也就意味著查詢集可以含有零個、一個或多個過濾器。過濾器基於所給的參數限制查詢的結果。
從SQL的角度講,查詢集與select語句等價,過濾器像where、limit、order by子句。
判斷某一個查詢集中是否有數據:
- exists():判斷查詢集中是否有數據,如果有則返回True,沒有則返回False。
2 兩大特性
1)惰性執行
創建查詢集不會訪問數據庫,直到調用數據時,才會訪問數據庫,調用數據的情況包括叠代、序列化、與if合用
例如,當執行如下語句時,並未進行數據庫查詢,只是創建了一個查詢集qs
qs = BookInfo.objects.all()
繼續執行遍歷叠代操作後,才真正的進行了數據庫的查詢
for book in qs:
print(book.btitle)
2)緩存
使用同一個查詢集,第一次使用時會發生數據庫的查詢,然後Django會把結果緩存下來,再次使用這個查詢集時會使用緩存的數據,減少了數據庫的查詢次數。
情況一:如下是兩個查詢集,無法重用緩存,每次查詢都會與數據庫進行一次交互,增加了數據庫的負載。
from booktest.models import BookInfo
[book.id for book in BookInfo.objects.all()]
[book.id for book in BookInfo.objects.all()]
情況二:經過存儲後,可以重用查詢集,第二次使用緩存中的數據。
qs=BookInfo.objects.all()
[book.id for book in qs]
[book.id for book in qs]
3 限制查詢集
可以對查詢集進行取下標或切片操作,等同於sql中的limit和offset子句。
註意:不支持負數索引。
對查詢集進行切片後返回一個新的查詢集,不會立即執行查詢。
如果獲取一個對象,直接使用[0],等同於[0:1].get(),但是如果沒有數據,[0]引發IndexError異常,[0:1].get()如果沒有數據引發DoesNotExist異常。
示例:獲取第1、2項,運行查看。
qs = BookInfo.objects.all()[0:2]
管理器Manager
管理器是Django的模型進行數據庫操作的接口,Django應用的每個模型類都擁有至少一個管理器。
我們在通過模型類的objects屬性提供的方法操作數據庫時,即是在使用一個管理器對象objects。當沒有為模型類定義管理器時,Django會為每一個模型類生成一個名為objects的管理器,它是models.Manager類的對象。
自定義管理器
我們可以自定義管理器,並應用到我們的模型類上。
註意:一旦為模型類指明自定義的過濾器後,Django不再生成默認管理對象objects。
自定義管理器類主要用於兩種情況:
1. 修改原始查詢集,重寫all()方法。
a)打開booktest/models.py文件,定義類BookInfoManager
#圖書管理器
class BookInfoManager(models.Manager):
def all(self):
#默認查詢未刪除的圖書信息
#調用父類的成員語法為:super().方法名
return super().filter(is_delete=False)
b)在模型類BookInfo中定義管理器
class BookInfo(models.Model):
...
books = BookInfoManager()
c)使用方法
BookInfo.books.all()
2. 在管理器類中補充定義新的方法
a)打開booktest/models.py文件,定義方法create。
class BookInfoManager(models.Manager):
#創建模型類,接收參數為屬性賦值
def create_book(self, title, pub_date):
#創建模型類對象self.model可以獲得模型類
book = self.model()
book.btitle = title
book.bpub_date = pub_date
book.bread=0
book.bcommet=0
book.is_delete = False
# 將數據插入進數據表
book.save()
return book
b)為模型類BookInfo定義管理器books語法如下
class BookInfo(models.Model):
...
books = BookInfoManager()
c)調用語法如下:
book=BookInfo.books.create_book("abc",date(1980,1,1))
django指定mysql數據庫 ORM查詢