Django之ORM-model模型屬性

  • 2019 年 10 月 3 日
  • 筆記

Django1.8.2中文文檔:Django1.8.2中文文檔 或者 https://yiyibooks.cn/xx/django_182/index.html

項目準備

注釋:關於項目準備,其實和後面的大部分內容都無關,或者說,可以不看,但為了自己和他人更好的體驗,還是放上去。

創建項目

1.創建項目test1000;

2.創建應用booktest;

註冊應用:

INSTALLED_APPS = [      'booktest.apps.BooktestConfig',  ]

 

3.創建資料庫

create database test1000 default charset utf8;

在settings文件下配置資料庫

DATABASES = {      'default': {          # 'ENGINE': 'django.db.backends.sqlite3',          'ENGINE': 'django.db.backends.mysql',          # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),          'NAME': 'test1000',  # 使用的資料庫的名字,資料庫必須手動創建          'USER': 'root',  # 鏈接mysql的用戶名          'PASSWORD': 'root',  # 對應用戶的密碼          'HOST': '127.0.0.1',  # 指定mysql資料庫所在電腦ip          'PORT': '3306',  # mysql服務的埠號      }  }
資料庫配置

 

4.在test1000/__init__.py中加如下內容:
注意:如果沒有pymysql需要先pip install

import pymysql  pymysql.install_as_MySQLdb()

 

5.定義模型類

class BookInfo(models.Model):      """圖書模型類"""      # 圖書名稱      btitle = models.CharField(max_length=20)      # 出版日期      bpub_date = models.DateField()      # 閱讀量      bread = models.IntegerField(default=0)      # 評論量      bcomment = models.IntegerField(default=0)      # 刪除標記      isDelete = models.BooleanField(default=False)      class HeroInfo(models.Model):      """圖書模型類"""      # 英雄名      hname = models.CharField(max_length=20)      # 性別      hgender = models.BooleanField(default=False)      # 備註      hcomment = models.CharField(max_length=200)      # 關係屬性      bhbook = models.ForeignKey(to="BookInfo")      # 刪除標記      isDelete = models.BooleanField(default=False)
定義圖書和英雄類

生成遷移數據

python manage.py makemigrations  python manage.py migrate

插入數據

INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('射鵰英雄傳', '1980-05-01', 12, 34, 0)  INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('天龍八部', '1986-07-24', 36, 40, 0)  INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('笑傲江湖', '1995-12-24', 20, 80, 0)  INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('雪山飛狐', '1987-11-11', 58, 24, 0)      INSERT INTO `test1000`.`booktest_heroinfo` (`hname`, `hgender`, `hbook_id`, `hcomment`, `isDelete`) 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);
插入數據

 

6.index頁面顯示書籍

創建模板templates文件夾;
去settings裡面註冊模板文件夾;
創建index頁面;

編寫index頁面,使用ul渲染書籍數據;
給index添加a標籤指向create路由;

<h2>index頁面</h2>  <a href="/create">添加</a>  <ul>      {% for book in books %}          <li>{{ book.btitle }}</li>      {% endfor %}  </ul>
index.html

 

編寫函數,使用模板渲染顯示書籍的頁面
編寫index函數,返回頁面渲染;

def index(request):      """顯示書籍"""      # 獲取所有書名      books = models.BookInfo.objects.all()      # 使用模板渲染書籍      return render(request, "booktest/index.html", {"books": books})
index函數

 

進行url匹配;
將路由導向booktest裡面的路由文件;

from django.conf.urls import include, url  from django.contrib import admin    urlpatterns = [      url(r'^admin/', admin.site.urls),      url(r'^', include('booktest.urls')),  # 包含booktest應用中的路由文件  ]
test1000/url.py

主要路由統一寫在此處,不再重複寫

# booktest/url.py    from django.conf.urls import url  from booktest import views    urlpatterns = [      url(r'^index/', views.index),  # 顯示圖書資訊      url(r'^create/', views.create),  # 添加一本書籍      url(r'^delete(d+)/', views.delete),  # 刪除一本書籍      url(r'^areas/$', views.areas),  # 自關聯案例  ]

 

7.進行書籍添加處理
編寫create函數,創建bookinfo對象,保存數據,導入redirect,給create函數返回redirect到/index頁面;

def create(request):      """增加一本書籍"""      # 1.創建bookinfo對象      b = models.BookInfo()      b.btitle = "流星蝴蝶劍"      b.bpub_date = date(1990, 1, 1)      # 2.保存進資料庫      b.save()      # 3.返回應答,讓瀏覽器再訪問首頁      # return HttpResponse("ok")      return redirect('/index')
create函數

給create函數進行路由匹配;

 

8.進行刪除書籍處理
給圖書後面添加刪除鏈接,鏈接應加上書籍id;

<a href="/create">添加</a>  <ul>      {% for book in books %}          <li>{{ book.btitle }}--<a href="/delete{{ book.id }}">刪除</a></li>      {% endfor %}  </ul>

編寫delete函數;

def delete(request, bid):      """刪除一本書籍"""      # 1.獲取書籍對象      book = models.BookInfo.objects.get(id=bid)      # 2.刪除書籍      book.delete()      # 3.重定向      return redirect('/index')
delete函數

進行路由匹配,注意路由匹配時應接收書籍id;即:

url(r'^delete(d+)/', views.delete),  # 刪除一本書籍

 

a標籤中url的/

<a href="/create">添加</a>

a標籤記得前面統一加上/;
沒加斜杠的,表示在當前的路由下進行拼接,比如現在在是http://127.0.0.1:8000/index,路由是create,那麼就會拼接成/index/create;
而加了斜杠就不會出現這個問題,斜杠表示http://127.0.0.1:8000/,會直接拼接到根路由下;

 

Django ORM

  • O:(objects)->類和對象。
  • R:(Relation)->關係,關係資料庫中的表格。
  • M:(Mapping)->映射。

ORM框架的功能:

  • a)能夠允許我們通過面向對象的方式來操作資料庫。
  • b)可以根據我們設計的模型類幫我們自動生成資料庫中的表格。
  • c) 通過方便的配置就可以進行資料庫的切換。

 

欄位屬性和選項

模型類屬性命名限制

  • 1)不能是python的保留關鍵字。
  • 2)不允許使用連續的下劃線,這是由django的查詢方式決定的。
  • 3)定義屬性時需要指定欄位類型,通過欄位類型的參數指定選項,語法如下:屬性名=models.欄位類型(選項)

欄位類型

使用時需要引入django.db.models包,欄位類型如下:

類型

描述

AutoField

自動增長的IntegerField,通常不用指定,不指定時Django會自動創建屬性名為id的自動增長屬性。
BooleanField 布爾欄位,值為True或False。
NullBooleanField 支援Null、True、False三種值。
CharField(max_length=字元長度)

字元串。參數max_length表示最大字元個數。

TextField 大文本欄位,一般超過4000個字元時使用。
IntegerField 整數。
DecimalField(max_digits=None, decimal_places=None)

十進位浮點數。

參數max_digits表示總位數。參數decimal_places表示小數位數。

FloatField 浮點數。參數同上,精確度不如上面的。
FileField 上傳文件欄位。
ImageField 繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片。
DateField

日期。年月日
參數auto_now表示每次保存對象時,自動設置該欄位為當前時間,用於"最後一次修改"的時間戳,它總是使用當前日期,默認為false。
參數auto_now_add表示當對象第一次被創建時自動設置當前時間,用於創建的時間戳,它總是使用當前日期,默認為false。
參數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤。

TimeField 時間,參數同DateField。小時分秒
DateTimeField 日期時間,參數同DateField。年月日時分秒

 

 選項

通過選項實現對欄位的約束,選項如下:

選項名 描述
default 默認值。
primary_key 若為True,則該欄位會成為模型的主鍵欄位,默認值是False,一般作為AutoField的選項使用。
unique 如果為True, 這個欄位在表中必須有唯一值,默認值是False。
db_index 若值為True, 則在表中會為此欄位創建索引,默認值是False。
db_column 欄位的名稱,如果未指定,則使用屬性的名稱。
null 如果為True,表示允許為空,默認值是False。
blank 如果為True,則該欄位允許為空白,默認值是False。

對比:null是資料庫範疇的概念,blank是表單驗證證範疇的。

經驗:當修改模型類之後,如果添加的選項不影響表的結構,則不需要重新做遷移,例如商品的選項中default和blank不影響表的結構;

如果想要更深入的了解模型的選型和欄位,建議看官方文檔,百度Django1.8.2.中文文檔即可。

 

單表查詢

配置MySQL的日誌文件

讓其產生mysql.log,即是mysql的日誌文件,裡面記錄了對mysql資料庫的操作記錄。
1).使用下面的命令打開mysql的配置文件,取消68,69行的注釋,然後保存。

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

2).重啟mysql服務,就會產生mysql日誌文件。

sudo service mysql restart

3).打開mysql的日誌文件

/var/log/mysql/mysql.log # mysql日誌文件所在位置

4).使用下面命令實時查看mysql文件的內容

sudo tail -f /var/log/mysql/mysql.log

 

查詢函數

通過模型類.object屬性可以調用如下函數,實現對模型類對應的數據表的查詢;
注意,查詢集裡面,還可以再次調用一下函數進行處理,即如果你通過filter等函數查詢出來的數據,還可以調用filter等函數進行處理;

函數名 功能 返回值 備註
get() 返回表中滿足條件的一條且只能有一條數據 返回對象;

如果查到多條數據,則拋異常:MultipleObjectsReturned
查詢不到數據,則拋異常:DoesNotExist

all() 返回模型類對應表格中的所有數據。 QuerySet類型 查詢集
filter() 返回滿足條件的數據 QuerySet類型

參數寫查詢條件;

條件格式:模型類屬性名__條件名=值。

exclude 返回不滿足條件的數據 QuerySet類型 參數寫查詢條件;
order_by 對查詢結果進行排序。 QuerySet類型 參數中寫根據哪些欄位進行排序。

 

filter方法示例:

1. 判等 exact。
例:查詢編號為1的圖書。

BookInfo.objects.get(id=1)  BookInfo.objects.get(id__exact=1)

2. 模糊查詢
例:查詢書名包含'傳'的圖書。contains

BookInfo.objects.filter(btitle__contains='傳')

例:查詢書名以'部'結尾的圖書 endswith 開頭:startswith

BookInfo.objects.filter(btitle__endswith='部')

3. 空查詢 isnull
select * from booktest_bookinfo where title is not null;
例:查詢書名不為空的圖書。isnull

BookInfo.objects.filter(btitle__isnull=False)

4. 範圍查詢 in
select * from booktest_bookinfo where id in (1,3,5)
例:查詢編號為1或3或5的圖書。

BookInfo.objects.filter(id__in = [1,3,5])

5. 比較查詢

  • gt(greate than) 大於
  • lt(less than) 小於
  • gte(equal) 大於等於
  • lte 小於等於

例:查詢編號大於3的圖書。

BookInfo.objects.filter(id__gt = 3)

6. 日期查詢
例:查詢1980年發表的圖書。

BookInfo.objects.filter(bpub_date__year=1980)

例:查詢1980年1月1日後發表的圖書。

from datetime import date  BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))

 

exclude方法示例:
例:查詢id不為3的圖書資訊。
BookInfo.objects.exclude(id=3)

order_by示例方法:
作用:進行查詢結果進行排序
降序(.all()可以省略)

# 例1:查詢所有圖書資訊,按照id從小到大順序進行排序;  BookInfo.objects.all().order_by('id')    # 按照升序排序  # 查詢所有圖書資訊,按照id從大到小順序進行排序;  BookInfo.objects.all().order_by('-id') # 按照降序排序  # 把id大於3的圖書資訊按閱讀量從大到小排序顯示。  BookInfo.objects.filter(id__gt=3).order_by('-bread') # 把id大於3的圖書資訊按閱讀量從大到小排序顯示。

 

Q對象

作用:用於查詢時條件之間的邏輯關係。not and or,可以對Q對象進行&|~操作。

使用之前需要先導入:

from django.db.models import Q

例:查詢id大於3且閱讀量大於30的圖書的資訊。

BookInfo.objects.filter(id__gt=3, bread__gt=30)  BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30))

例:查詢id大於3或者閱讀量大於30的圖書的資訊。

BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))

例:查詢id不等於3圖書的資訊。

BookInfo.objects.filter(~Q(id=3))

 

F對象

作用:用於類屬性之間的比較。比如要查詢評論量大於閱讀量的文章書籍時就可以使用;

使用之前需要先導入:

from django.db.models import F

例:查詢圖書閱讀量大於評論量圖書資訊。

BookInfo.objects.filter(bread__gt=F('bcomment'))

例:查詢圖書閱讀量大於2倍評論量圖書資訊。

BookInfo.objects.filter(bread__gt=F('bcomment')*2)

 

聚合函數

作用:對查詢結果進行聚合操作。

  • sum
  • count
  • avg
  • max
  • min

aggregate:調用這個函數來使用聚合。 返回值是一個字典

使用前需先導入聚合類:

from django.db.models import Sum,Count,Max,Min,Avg

例:查詢所有圖書的數目。

BookInfo.objects.all().aggregate(Count('id'))  {'id__count': 5}

例:查詢所有圖書閱讀量的總和。

BookInfo.objects.aggregate(Sum('bread'))  {'bread__sum': 126}

 


count函數

返回一個數字
作用:統計滿足條件數據的數目。

例:統計所有圖書的數目。

BookInfo.objects.all().count()  BookInfo.objects.count()  結果:5

例:統計id大於3的所有圖書的數目。

BookInfo.objects.filter(id__gt=3).count()

 

查詢相關函數小結

  • get:返回一條且只能有一條數據,返回值是一個對象, 參數可以寫查詢條件。
  • all:返回模型類對應表的所有數據,返回值是QuerySet。
  • fiter:返回滿足條件的數據,返回值是QuerySet,參數可以寫查詢條件。
  • exclude:返回不滿足條件的數據,返回值是QuerySet,參數可以寫查詢條件。
  • order_ by:對查詢結果進行排序,返回值是QuerySet, 參數中寫排序的欄位。

注意:

  • 1. get, flter,exclude函數中可以寫查詢條件,如果傳多個參數,條件之間代表且的關係。
  • 2. all, fiter, exclude, order. by函數的返回值是QuerySet類的實例對象,叫做查詢集。

 

from diango.db.models import F,Q Sum,Count Avg, Max,Min

  • F對象:用於類屬性之間的比較。
  • Q對象:用於條件之間的邏輯關係。
  • aggregate:進行聚合操作,返回值是一個字典,進行聚合的時候需要先導入聚合類。
  • count:返回結果集中數據的數目,返回值是一個數字。

注意:
對一個QuerySet實例對象,可以繼續調用上面的所有函數。


參考文檔:
http://python.usyiyi.cn/translate/django_182/ref/models/querysets.html

 

查詢集

all, filter, exclude, order_by調用這些函數會產生一個查詢集,QuerySet類對象可以繼續調用上面的所有函數。

查詢集特性

1)惰性查詢:只有在實際使用查詢集中的數據的時候才會發生對資料庫的真正查詢。
2)快取:當使用的是同一個查詢集時,第一次的時候會發生實際資料庫的查詢,然後把結果快取起來,之後再使用這個查詢集時,使用的是快取中的結果。

限制查詢集

可以對一個查詢集進行取下標或者切片操作來限制查詢集的結果。
對一個查詢集進行切片操作會產生一個新的查詢集,下標不允許為負數。

取出查詢集第一條數據的兩種方式:

 

方式  說明
b[0]  如果b[0]不存在,會拋出IndexError異常
b[0:1].get()  如果b[0:1].get()不存在,會拋出DoesNotExist異常。

exists:判斷一個查詢集中是否有數據。True False

books = BookInfo.objects.all()  books1 = books[0:0]  book.exists()  # True  book1.exists()  # False

 

Tags: