04-Django模型(1)
- 2019 年 10 月 11 日
- 筆記
—恢復內容開始—
模型
MTV圖解
ORM
ORM全拼:Object-Relation-Mapping翻譯就是對象關係映射。在MVC/MTV設計模式中的Model模組中都包括ORM。主要實現模型對象到關係資料庫數據的映射。比如:把資料庫表中每條記錄映射為一個模型對象
ORM圖解
優點:
只需要面向對象編程,不需要面向資料庫編寫程式碼。對資料庫的操作都轉化為對類屬性和方法的操作,不用編寫各種資料庫的sql語句
實現了數據模型與資料庫的解耦,屏蔽了不同資料庫操作上的差異。通過簡單地配置就可以輕鬆更換資料庫,而不需要修改程式碼。
缺點:
相比較直接使用SQL語句操作資料庫,有性能缺失。會轉化為sql語句在執行。多了流程。根據對象的操作轉換成sql語句,根據查詢的結果轉化成對象,在映射過程中有性能損失。
項目準備
1、創建項目
django-admin startproject BookManager
2、創建應用
python manage.py startapp Book
3、安裝應用
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'Book', ]
4、本地化
LANGUAGE_CODE = 'zh-Hans' TIME_ZONE = 'Asia/Shanghai'
5、創建模板路徑
在應用同級目錄下,創建templates模板文件
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', #模板路徑 'DIRS': [os.path.join(BASE_DIR,"templates")], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
6、應用中分發路由
from django.contrib import admin from django.urls import path from Book import views urlpatterns = [ path('admin/', admin.site.urls), path('booklist/', views.bookList), ]
7、準備視圖函數
from django.shortcuts import render from django.http import HttpResponse # Create your views here. #書籍列表資訊視圖 def bookList(request): return HttpResponse("ok")
8、開啟伺服器,測試項目
python manage.py runserver
http://127.0.0.1:8000/
MYSQL資料庫
Django項目默認採用sqlite3資料庫,但是Web項目首選的資料庫是mysql資料庫,所以我們需要修改Django項目默認的資料庫為mysql資料庫
安裝pymysql包
pymysql包用於跟mysql資料庫交互,沒有pymysql包會報錯:Error loading MySQLdb module: No module named MySQLdb
pip3 install pymysql
pymysql包配置:
配置項目mysql資料庫(settings.py)
默認配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
配置mysql資料庫:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 資料庫引擎 'NAME': 'Bookdb', # 資料庫名稱 'HOST': 'localhost', # 資料庫主機(建議使用主機真實IP) 'PORT': '3306', # 資料庫埠 'USER': 'root', # 資料庫用戶名 'PASSWORD': '', # 資料庫密碼 } }
創建項目mysql資料庫
打開cmd終端,打開資料庫,鏈接資料庫。創建資料庫名字:
create database bookdb charset=utf8;
use Bookdb;
show tables;
#退出資料庫 exit
欄位類型
當為項目創建好mysql類型的資料庫bookdb後,需要創建模型類並生成和執行遷移表,從而創建資料庫表。但是在創建模型類需要指定模型屬性和屬性類型。
模型屬性和屬性類型,也就是對應資料庫中的欄位和欄位類型
模型類定義屬性:
語法:屬性名 = models.欄位類型(選項)
# 書籍資訊模型 class Book(models.Model): name = models.CharField(max_length=20) #圖書名稱
備註:屬性名1、不允許使用python的保留關鍵字,2、不允許使用mysql的保留關鍵字,3、不允許使用連續的下劃線,因為Django的查詢語法就是連續的下劃線。
欄位類型
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:浮點數
DateField[auto_now=False, auto_now_add=False]):日期,參數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
對比:null是資料庫範疇的概念,blank是表單驗證範疇的
db_column:欄位的名稱,如果未指定,則使用屬性的名稱
db_index:若值為True, 則在表中會為此欄位創建索引,默認值是False
default:默認值
primary_key:若為True,則該欄位會成為模型的主鍵欄位,默認值是False,一般作為AutoField的選項使用
unique:如果為True, 這個欄位在表中必須有唯一值,默認值是False
注意:Django會自動為表創建主鍵欄位 如果使用選項設置某屬性為主鍵欄位後,Django不會再創建自動增長的主鍵欄位 默認創建的主鍵欄位為id,可以使用pk代替,pk全拼為primary key
關係欄位類型
關係型資料庫的關係包括三種類型:
ForeignKey:一對多,將欄位定義在多的一端中
ManyToManyField:多對多,將欄位定義在任意一端中
OneToOneField:一對一,將欄位定義在任意一端中
可以維護遞歸的關聯關係,使用self指定,詳見“自關聯”
元模型類
作用:在模型類中定義 元類Meta,用於設置元資訊,用db_table 自定義表的名字
# 書籍資訊模型 class BookInfo(models.Model): name = models.CharField(max_length=20) #圖書名稱 class Meta: #元資訊類 db_table = 'bookinfo' #自定義表的名字
#在資料庫中更改表名
查看錶結構(資料庫的客戶端查看)
desc 表明
定義模型
定義的模型可以是這個樣子
#書籍資訊 ("與時間做朋友","2002-08-22","45.21","中信出版社","athor_id") #人物資訊 ("李笑來","男","年齡","家庭地址","電話")
因此模型程式碼如下:
from django.db import models # Create your models here. #創建作者資訊表 class Authors(models.Model): name = models.CharField(max_length=20)#作者名字 gender = models.BooleanField(default=True)#性別 age = models.IntegerField()#年齡 addr = models.CharField(max_length=60) tel = models.IntegerField() #元類修改表名 class Meta: db_table = "authors" #創建書籍資訊 class Books(models.Model): name = models.CharField(max_length=20)#書名 pub_data = models.DateField(null=True)#出版日期 #參數max_digits表示總位數 參數decimal_places表示小數位數 price = models.DecimalField(max_digits=8,decimal_places=2)#價格 publish = models.CharField(max_length=20) #外鍵 將欄位定義在多的一端中 級聯刪除 author = models.ForeignKey(Authors,on_delete=models.CASCADE) #修改表名(元類) class Meta: db_table = "books"
模型遷移不要忘記:
python manage.py makemigrations python manage.py migrate
查看錶結構:
去站點插點數據(如果嫌慢就用sql語句插數據)(需要設置站點,1、註冊管理模型類,需要顯示完整的,重寫類,list_display重新註冊,啟動超級用戶,python manage.py createsuperuser)
展示模型數據
網址:http://127.0.0.1:8000/booklist
路由部分:
from django.contrib import admin from django.urls import path from Book import views urlpatterns = [ path('admin/', admin.site.urls), path('booklist/', views.bookList), ]
視圖部分:
from django.shortcuts import render from django.http import HttpResponse # Create your views here. from Book.models import * #書籍列表資訊視圖 def bookList(request): #查詢資料庫書籍資訊 booklist = Books.objects.all() #構造上下文 content = {"booklist":booklist} #傳入模板 返回由視圖發送給瀏覽器 return render(request,"Book/booklist.html",content)
模板部分:
from django.db import models # Create your models here. #創建作者資訊表 class Authors(models.Model): name = models.CharField(max_length=20)#作者名字 gender = models.BooleanField(default=True)#性別 age = models.IntegerField()#年齡 addr = models.CharField(max_length=60) tel = models.IntegerField() #元類修改表名 class Meta: db_table = "authors" def __str__(self): return self.name #創建書籍資訊 class Books(models.Model): name = models.CharField(max_length=20)#書名 pub_data = models.DateField(null=True)#出版日期 #參數max_digits表示總位數 參數decimal_places表示小數位數 price = models.DecimalField(max_digits=8,decimal_places=2)#價格 publish = models.CharField(max_length=20) #外鍵 將欄位定義在多的一端中 級聯刪除 author = models.ForeignKey(Authors,on_delete=models.CASCADE) #修改表名(元類) class Meta: db_table = "books" def __str__(self): return self.name
結果:
模型中重要的實例方法和屬性
模型實例方法
str : 在將對象轉換成字元串時會被調用 save : 將模型對象保存到資料庫表中 delete : 將模型對象從資料庫表中刪除
objects模型屬性
objects : 管理器對象是Manager類型的對象,定義在from django.db import models中用於模型對象和資料庫交互
是默認自動生成的屬性,但是可以自定義管理器對象自定義管理器對象後,Django不再生成默認管理器對象objects
自定義管理器對象,原本默認的是objects = models.Manager(),可以自定義,重新實例化管理器對象。
查詢操作
- 查詢集:表示從資料庫中獲取的模型對象集合
- 在管理器上調用過濾器方法會返回查詢集
- 查詢集可以含有0個、一個或多個過濾器
- 過濾器:基於所給的參數限制查詢的結果
- 提示:從sql的角度,查詢集和select語句等價,過濾器像where和limit語句
返回列表的過濾器如下:
all():返回所有的數據 filter():返回滿足條件的數據 exclude():返回滿足條件之外的數據,相當於sql語句中where部分的not關鍵字 order_by():返回排序後的數據
返回單個對象的過濾器如下:
get():返回單個滿足條件的對象 如果未找到會引發"模型類.DoesNotExist"異常 如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常 count():返回當前查詢的總條數 aggregate():聚合 exists():判斷查詢集中是否有數據,如果有則返回True,沒有則返回False
查詢集的特點
1、惰性執行:創建查詢集不會訪問資料庫,直到在模板中調用數據時,才會訪問資料庫。
調用數據的情況包括迭代、序列化、與if合用
2、快取:查詢集的結果被存下來之後,再次查詢相同數據時會使用之前快取的數據
每個查詢集都包含一個快取來最小化對資料庫的訪問,第一次查詢數據後,Django會將查詢集快取起來,並返回請求的結果,再次查詢相同數據時將重用快取的結果。
限制查詢集
- 查詢集返回列表,可以使用下標的方式進行限制,等同於sql中的limit和offset語句
- 注意:不支援負數索引
- 使用下標後返回一個新的查詢集,不會立即執行查詢
-
如果獲取一個對象,直接使用
[0]
,等同於[0:1].get()
- 但是如果沒有數據,
[0]
引發IndexError
異常,[0:1].get()
引發DoesNotExist
異常
- 但是如果沒有數據,
基礎條件查詢
查詢語法
filter(模型屬性__條件運算符=值) 例: filter(name__contains='時')
說明:查詢語句是屬性名稱和比較運算符間使用兩個下劃線相連,所以定義的模型屬性名不能包括多個下劃線
實現sql中where的功能,可以調用過濾器filter()、exclude()、get()
查詢需求
# 1.查詢id為1的書籍 # 2.查詢書名包含‘時間’的書籍 # 3.查詢書名以‘觀’結尾的書籍 # 4.查詢書名不為空的書籍 # 5.查詢價格為50或52的書籍 # 6.查詢價格大於52的書籍 # 7.查詢id不等於3的書籍 # 8.查詢2019年發表的書籍 # 9.查詢2000年1月1日後發表的書籍
查詢實現
1.查詢id為1的書籍(exact:判斷相等)
#1、查詢id為1的書籍(exact: 判斷相等)<QuerySet [<Books: 與時間做朋友>]>
book = Books.objects.all()
book1 = book.filter(id__exact=1)
2.查詢書名包含‘時間’的書籍(contains:是否包含)
book = Books.objects.all() book1 = book.filter(name__contains="局觀")
#<QuerySet [<Books: 大局觀>]>
3.查詢書名以‘與’開始的書籍(startswith,endswith)
book = Books.objects.all() book1 = book.filter(name__startswith="與") print(book1)
4.查詢書名不為空的書籍(isnull:是否為null)
book = Books.objects.all() book1 = book.filter(name__isnull=False) print(book1)
5.查詢價格為50或52的書籍(in:是否包含在這範圍內)
book = Books.objects.all() book1 = book.filter(price__in=[50,52]) print(book1)
6.查詢價格大於52的書籍(gt,gte,it,ite:大於,大於等於,小於,小於等於)
book = Books.objects.all() book1 = book.filter(price__gt=52) print(book1)
7.查詢id不等於3的書籍(exclude:條件以外的數據)
book = Books.objects.all() book1 = book.exclude(id=3) print(book1)
8.查詢2019年發表的書籍(yearmonthdayweek_dayhourminutesecond:對日期時間類型的屬性進行運算)
book = Books.objects.all() book1 = book.filter(pub_data__year=2019) print(book1)
9.查詢2000年1月1日後發表的書籍
from datetime import date book = Books.objects.all() book1 = book.filter(pub_data__gt=date(2000,1,1)) print(book1)
備註:
exact
、contains
、startswith
、endswith
運算符都區分大小寫- 在這些運算符前加上
i
表示不區分大小寫 - 如
iexact
、icontains
、istartswith
、iendswith
其他特殊查詢下一節分享總結(F和Q查詢,聚合函數,關聯查詢)