ORM Object relational mapping 對象關係映射,把類和數據庫表對應,把對象和表記錄對應,經過類和對象操做數據庫表中的數據,而不須要編寫SQL語句python
一、使用MySQL數據庫首先須要安裝驅動程序mysql
pip install PyMySQL
二、在Django的工程同名子目錄的__init__.py中添加以下語句,做用是讓Django的ORM能以mysqldb的方式來調用PyMySQLgit
from pymysql import install_as_MySQLdb install_as_MySQLdb()
三、編輯settings.py,修改DATABASE配置信息sql
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1',#主機 'PORT': 3306, #端口 'USER': 'root', #數據庫用戶名 'PASSWORD': 'root', #數據庫用戶密碼 'NAME': 'demo' #數據名字 } }
四、在MySQL中建立數據庫shell
create database demo default charset=utf8;
建立應用book,在models.py文件中定義模型數據庫
from django.db import models class Book(models.Model): title = models.CharField(max_length=20, verbose_name='名稱') pub_date = models.DateField(verbose_name='發佈日期') read_num = models.IntegerField(default=0, verbose_name='閱讀量') comment_num = models.IntegerField(default=0, verbose_name='評論量') is_delete = models.BooleanField(default=False, verbose_name='邏輯刪除') class Meta: db_table = 'book' #指明數據庫表名 verbose_name = '圖書' #在admin站點中顯示的名稱 verbose_name_plural = verbose_name #顯示覆數的名稱 def __str__(self): """定義每一個數據對象的顯示信息""" return self.title class Hero(models.Model): GENDER_CHOICES = ( (0, 'male'), (1, 'female') ) name = models.CharField(max_length=20, verbose_name='名稱') gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性別') comment = models.CharField(max_length=200, null=True, verbose_name='描述信息') book = models.ForeignKey(Book, on_delete=models.CASCADE, verbose_name='圖書') #CASCADE級聯,刪除主表數據時連同一塊兒刪除外鍵表中的數據 is_delete = models.BooleanField(default=False, verbose_name='邏輯刪除') class Meta: db_table = 'hero' verbose_name = '英雄' verbose_name_plural = verbose_name def __str__(self): return self.name
關於主鍵django
id
,
類型 | 說明 |
---|---|
AutoField | 自動增加的IntegerField,一般不用指定,不指定時Django會自動建立名爲id的自動增加屬性 |
BooleanField | 布爾字段,值爲True或False |
NullBooleanField | 支持Null、True、False三種值 |
CharField | 字符串,必須指定:max_length ,表示最大字符個數 |
TextField | 大文本字段,通常超過4000個字符時使用 |
IntegerField | 整數 |
DecimalField | 十進制浮點數,用python中的Decimal實例來表示 必須指定: max_digits 總位數,decimal_places 小數位數。 |
FloatField | 浮點數 |
DateField | 日期 1) 參數 auto_now 表示每次修改保存對象時,自動設置該字段爲當前時間,用於保存"最後一次修改"時間,默認爲False; 2) 參數 auto_now_add 表示當對象第一次被建立時自動設置保存當前時間,用於保存"建立時間"時間,默認爲值爲False; 3) 參數 auto_now_add 和auto_now 是相互排斥的,不能同時用到一個屬性中 |
TimeField | 時間,參數同DateField |
DateTimeField | 日期時間,參數同DateField |
FileField | 上傳文件字段 |
ImageField | 繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片 |
選項 | 默認值 | 描述 | 是否要遷移修改表結構 |
---|---|---|---|
null | False | True表示表字段容許爲空 | 是 |
unique | False | True表示表字段不能重複 | 是 |
db_column | 屬性名稱 | 表字段名稱 | 是 |
primary_key | False | True表示字段設置爲了主鍵,通常做爲AutoField的選項使用 | 是 |
default | - | 默認值 | 否 |
blank | False | 在django管理後臺新增或編輯一條表數據時,該字段是否容許爲空; null是數據庫範疇的概念,blank是表單驗證範疇的 |
否 |
choices | - | 在django管理後臺新增或編輯一條表數據時,該字段顯示爲下拉框,默認爲編輯框 | 否 |
blank:blank屬性默認值爲false, 表示錄入一條數據時,當前字段必須填寫,不能爲空,不然js端js校驗不經過,例如:下圖的comment員工備註信息字段。緩存
外鍵app
ForeignKey
: 一對多,將 關聯屬性
定義在多的一端中ManyToManyField
: 多對多,將 關聯屬性
定義任意一方中OneToOneField
: 一對一,將 關聯屬性
定義在任意一方中
定義完模型類之後,咱們須要把模型生成到數據庫裏面去ide
python manage.py mikemigrations
python manage.py migrate
在Django交互環境中,能夠直接執行django項目代碼,相似ipython交換環境
經過shell命令進入Django交換環境
insert into book(name,pub_date,read_num,comment_num,is_delete) values ('射鵰英雄傳','1980-5-1',12,34,0), ('天龍八部','1986-7-24',36,40,0), ('笑傲江湖','1995-12-24',28,18,0), ('雪山飛狐','1987-11-11',58,24,0); insert into hero(name,gender,book_id,comment,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), ('袁紫衣',0,4,'六合拳',0);
如今咱們能夠在Django交互環境測試數據庫操做,首先咱們來對數據庫進行增長操做,有兩種方式
1)模型類對象.save()
from book.models import Book, Hero from datetime import date book = Book( title='西遊記', pu_date=date(1988,1,1), read_num=10, comment_num=10 ) book.save
2)經過模型類.objects.creare()保存
from book.models import Book, Hero b = Book.objects.get(title='西遊記') Hero.objects.create( name='沙悟淨', gender=0, book=book ) 或者 Hero.objects.create( name='沙悟淨', gender=0, book_id=book.id )
刪除記錄有兩種方式
1)模型類對象.delete()
book = Book.objects.get(id=1)
book.delete()
2)模型類.filter(條件).delete()
Book.objects.filter(id=1).delete()
注意事項: on_delete選項
models.CASCADE
,當刪除圖書時,會刪除相關聯的英雄on_delete
爲 PROTECT
修改記錄有如下兩種方式
1)模型類對象.save()
h = Hero.objects.get(name='沙悟淨') h.name = '沙僧' h.save()
2)模型類.filter()條件.update(屬性1=值1, 屬性2=值2, ...)
Hero.objetcs.filter(name='豬八戒').update(name='豬悟能')
get 查詢單一結果,若是不存在或拋出模型類.DoesNotExist異常,經過存在多條記錄會拋出MultipleObjectsReturned異常
#查詢id爲3的圖書 In [7]: Book.objects.get(id=3) Out[7]: <Book: 笑傲江湖> #查詢id爲100的圖書,該圖書其實不存在 In [8]: Book.objects.get(id=100) --------------------------------------------------------------------------- DoesNotExist Traceback (most recent call last) ... #查詢is_delete爲false的圖書,有多條 In [9]: Book.objects.get(is_delete=0) --------------------------------------------------------------------------- MultipleObjectsReturned Traceback (most recent call last)
all 查詢多個結果
In [6]: Book.objects.all()
Out[6]: <QuerySet [<Book: 射鵰英雄傳>, <Book: 天龍八部>, <Book: 笑傲江湖>, <Book: 雪山飛狐>, <Book: 西遊記>]>
count 查詢結果數量
In [10]: Hero.objects.count()
Out[10]: 20
1)判等: exact
In [11]: Book.objects.filter(id__exact=1) Out[11]: <QuerySet [<Book: 射鵰英雄傳>]> 可簡寫爲 In [12]: Book.objects.filter(id=1) Out[12]: <QuerySet [<Book: 射鵰英雄傳>]>
2)模糊查詢: contains / endswith / startswith
In [13]: Hero.objects.filter(name__contains='不') Out[13]: <QuerySet [<Hero: 嶽不羣>, <Hero: 東方不敗>]>
In [14]: Hero.objects.filter(name__startswith='黃') Out[14]: <QuerySet [<Hero: 黃蓉>, <Hero: 黃藥師>]>
3)空查詢: isnull
In [17]: Book.objects.filter(title__isnull=False)
Out[17]: <QuerySet [<Book: 射鵰英雄傳>, <Book: 天龍八部>, <Book: 笑傲江湖>, <Book: 雪山飛狐>, <Book: 西遊記>]>
4)範圍查詢: in
In [20]: Book.objects.filter(id__in=[1,3,5])
Out[20]: <QuerySet [<Book: 射鵰英雄傳>, <Book: 笑傲江湖>, <Book: 西遊記>]>
5)比較查詢: gt、lt、gte、lte
In [21]: Book.objects.filter(read_num__gt=20)
Out[21]: <QuerySet [<Book: 天龍八部>, <Book: 雪山飛狐>]>
6)日期查詢: year、month、day、week_day、hour、minute、second
In [22]: Book.objects.filter(pub_date__year=1980)
Out[22]: <QuerySet [<Book: 射鵰英雄傳>]>
In [23]: Book.objects.filter(pub_date__gt=date(1980,1,1))
Out[23]: <QuerySet [<Book: 射鵰英雄傳>, <Book: 西遊記>]>
以前查詢都是對象的屬性與常量值比較,兩個屬性怎麼比較?這就須要用到F對象
須要導包: from django.db.models import F
語法: F(屬性名)
In [25]: from django.db.models import F In [26]: Book.objects.filter(read_num__gte=F('comment_num')) Out[26]: <QuerySet [<Book: 雪山飛狐>, <Book: 西遊記>]>
能夠在F對象上使用算數運算
In [27]: from django.db.models import F
In [28]: Book.objects.filter(read_num__gt=F('comment_num') * 2)
Out[28]: <QuerySet [<Book: 雪山飛狐>]>
做用: 對查詢條件進行與 或 非(& | ~)的邏輯操做
須要導包: from django.db.models import Q
與: Q(查詢條件1) & Q(查詢條件2)
In [29]: from django.db.models import Q In [30]: Hero.objects.filter(Q(id__gt=2) & Q(name__contains='黃')) Out[30]: <QuerySet [<Hero: 黃藥師>]> 能夠簡寫爲 In [31]: Hero.objects.filter(id__gt=2, name__contains='黃') Out[31]: <QuerySet [<Hero: 黃藥師>]>
或: Q(查詢條件1) | Q(查詢條件2)
In [34]: Hero.objects.filter(Q(id__lt=2) | Q(name__contains='不')) Out[34]: <QuerySet [<Hero: 郭靖>, <Hero: 嶽不羣>, <Hero: 東方不敗>]>
非: ~Q(查詢條件)
Hero.objects.filter(~Q(id=3))
做用: 對查詢結果進行排序,默認爲升序
用法:
In [37]: Book.objects.all().order_by('-id') Out[37]: <QuerySet [<Book: 西遊記>, <Book: 雪山飛狐>, <Book: 笑傲江湖>, <Book: 天龍八部>, <Book: 射鵰英雄傳>]>
做用: 聚合操做,對多行查詢結果中的一列進行操做,返回一個值
用法: 模型類.objects.aggregate(聚合類('屬性名'))
In [38]: from django.db.models import Avg In [39]: Book.objects.aggregate(Avg('read_num')) Out[39]: {'read_num__avg': 25.2}
1)、由 一類對象 查詢 多類對象: 一類對象.多類名小寫_set.all()
In [42]: b = Book.objects.get(title='西遊記') In [43]: b.hero_set.all() Out[43]: <QuerySet [<Hero: 孫悟空>, <Hero: 豬悟能>, <Hero: 沙僧>]>
2)、由 多類對象 查詢 一類對象: 多類對象.關聯屬性
In [44]: h = Hero.objects.get(name='郭靖') In [45]: h.book Out[45]: <Book: 射鵰英雄傳>
經過模型類實現上述兩個案例
In [48]: Hero.objects.filter(book__title='西遊記') Out[48]: <QuerySet [<Hero: 孫悟空>, <Hero: 豬悟能>, <Hero: 沙僧>]> In [49]: Book.objects.filter(hero__name='郭靖') Out[49]: <QuerySet [<Book: 射鵰英雄傳>]>
查詢集,也稱查詢結果集、QuerySet,表示從數據庫中獲取的對象集合,當調用一下過濾器方法時,Django會返回查詢集(而不是簡單的列表)
對查詢集能夠再次調用過濾器進行過濾
Book.objects.filter(read_num__gt=30).order_by('pub_date')
查詢集兩大特性
1)惰性執行
建立查詢集不會訪問數據庫,直到調用數據時,纔會訪問數據庫,調用數據的狀況包括迭代、序列化、與if合用
例如,當執行以下語句時,並未進行數據庫查詢,只是建立了一個查詢集qs
qs = Book.objects.all()
繼續執行遍歷迭代操做後,才真正的進行數據庫查詢
for book in qs: print(book.title)
2)緩存
from Book.models import Book [book.id for book in Book.objects.all()] [book.id for book in Book.objects.all()]
from Book.models import Book list=Book.objects.all() [book.id for objects in list] [book.id for objectsin list]
限制查詢集
能夠對查詢集進行取下標或切片操做,等同於sql中的limit和offset子句(注意,不支持負數索引)
對查詢集進行切片後返回一個新的查詢集,不會當即執行查詢
若是獲取一個對象,直接使用[0],等同於[0:1].get(),可是若是沒有數據,[0]引起IndexError異常,[0:1].get()引起DoesNotExist異常
qs = Book.objects.all()[0:2]
能夠自定義模型管理器,好比如下兩種場景:
注意:自定義後模型管理器後, Django 將再也不自動生成默認的 objects
# 在book.models.py文件添加如下代碼, 自定義模型管理器 class BookManager(Manager): def all(self): """重寫all方法:只返回沒有刪除的部門""" return super().all().filter(is_delete=False) def create_book(self, title, pub_date): """封裝新增圖書的方法,方便調用""" book = Book() book.title = title book.pub_date = pub_date book.save() return book # 自定義模型管理器 class Book(models.Model): """部門類""" ... # 自定義模型管理器 objects = BookManager()