Django篇(二)
- 2019 年 10 月 6 日
- 筆記
配置使用mysql資料庫
之前我們使用的是Django中自帶的資料庫sqlite資料庫。
這篇文章讓我們切換成mysql,不會MySQL基礎的可以去查詢資料庫篇的文章。
1、創建項目
2、創建應用
3、註冊應用
4、修改setting.py來讓我們的Django框架支援mysql資料庫。
在setting.py找到DATABASES,修改成:
DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql',
'NAME':'student',
'USER':'root',
'PASSWORD':'123456',
'HOST':'localhost',
'PORT':3306,
}
}
ENGINE:選擇資料庫
NAME:資料庫的名字
USER:登陸帳號
PASSWORD:密碼
HOST:本地填寫localhost,不是就寫ip地址
PORT:3306.
5、我們還需要安裝操作mysql的模組
在虛擬環境中pip instal pymysql
6、在test3下的test3下的__init__添加:
import pymysql
pymysql.install_as_MySQLdb()
此時我們運行項目就不會有問題了。
常見模型欄位屬性
模型屬性命名:
1、不能是python保留關鍵字
2、不允許出現聯繫的下劃線
欄位類型
第一篇文章中我們僅僅了解了幾個。
接下來我們重新了解一下有什麼其他模型。
首先在使用時,我們需要導入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表示允許的最多位數,
decimal_places表示小數的位數
FloatField;
浮點數,參數和上面的一樣,但是沒有上面的精確。
DateField:
日期(年月日),參數autu_now=True,表示每次保存的,自動的添加現在的時間
參數auto_now_add=True,表示添加時候的時間,
這兩個屬性是互斥的,只能存在一個。
TimeField:
時間(時分秒):參數和上面的一樣。
DateTimeField:
時間(年月日,時分秒),參數同上。
FileField:
上傳文件欄位。
ImageField:
繼承FileField,對上傳的照片進行校驗,保證是有效的照片。
公用屬性
default:默認值
primary_key:若為True,則是主鍵,一般搭配AutoField使用。
unique:唯一值
db_index:若為True,則會為此欄位創建索引。
db_column:指定欄位名字,未指定會使用屬性名稱。
null:若為True,表示該欄位允許為空。
blank:這個屬性與後台admin有關,是否允許在後台添加值的時候是否為空。
注意:我們在添加屬性的時候如果影響了表結構,就需要遷移,default和blank不影響表結構。
更多模型欄位,請參考Django官方文檔。寫的明明白白。
查詢
我們在Django中通過操作模型類去做增刪改查,sql語句那麼多,我們同樣可以進行增刪改查。
其中最複雜的也就是查詢了。下面我們來看一下。
查詢函數
我們在Django中通過:模型類.objects屬性調用以下函數來進行查詢
get:
返回表中滿足條件的一條數據,有且只能有一條,查詢出多條會報異常。
查詢不到數據也會報異常。
all:
返回全部數據,返回的類型是QuerySet。
filter:
返回符合條件的,和get不同,這個可以返回多條數據。返回的類型是QuerySet。
exclude:
返回不滿足此條件的,也是可以返回多條數據,返回類型也是QuerySet。
order_by:
對查詢的結果進行排序,返回類型也是QuerySet。
以下我們以模型類為stuinfo是實例。
get實例:
查詢id為1的數據:
stuinfo.objects.get(id = 1)
all實例:
查詢所有數據:
stuinfo.objects.all()
filter實例:
條件格式:欄位名__條件名 = 值
1、等於條件名為exact
查詢年齡(age)為18的人
student.objects.filter(age__exact = 18)
2、模糊查詢條件名為contains
2.1查詢名字(name)中含有張的人
student.objects.filter(name__contains='張')
2.2查詢以名字三結尾的人
student.objects.filter(name__endswith='三')
2.3查詢以李開頭的人
student.objects.filter(name__startswith='李')
3、空查詢 isnull
3.1查詢備註(context)為空的人
student.objects.filter(context__isnull=True)
3.2查詢備註(context)不為空的人
student.objects.filter(context__isnull=False)
4、範圍查詢 in
查詢id等於1和2的人
student.objects.filter(id__in=[1,2])
5、比較查詢 gt(大於) lt(小於) gte(大於等於) lte(小於等於)
5.1查詢id大於3的人
student.objects.filter(id__gt=3)
5.2查詢id大於等於3的人
student.objects.filter(id__gte=3)
5.3查詢id小於3的人
student.objects.filter(id__lt=3)
5.4查詢id小於等於3的人
student.objects.filter(id__lte=3)
6、日期查詢
6.1查詢生日(bir_date)是1998年出生的人
student.objects.filter(bir_date__year=1998)
6.2查詢生日(bir_date)是5月出生的人
student.objects.filter(bir_date__month=5)
6.3查詢生日(bir_date)是1998,1,1以後出生的
from datetime import date
student.objects.filter(bir_date__gt=date(1998,1,1))
exclude實例
查詢id不等以1的人
student.objects.exclude(id = 1)
order_by實例
查詢所有人按照ids從小到大排序
student.objects.all().order_by('id')
查詢所有時,可以省略all()
student.objects.order_by('id')
查詢所有人按照ids從大到小排序
student.objects.all().order_by('-id')
也可以根據多個欄位排序
根據id和age進行排序
student.objects.all().order_by('id','age')
注意:以上只要返回值為QuerySet類型,都可以再次進行以上任何操作。
Q對象
以上我們都是單個條件進行查詢,那如果多個條件呢?
我們可以在上面獲取的對象再次進行篩選,也就是注意中說的那句話,但是很麻煩。
因此Django為我們提供了Q模組來幫助我們多條件查詢。
首先我們需要導入Q模組:
from django.db.models import Q
Q實例:
在實例之前,在Filter中是可以進行and操作的,但是不能進行or操作。
比如查詢id大於3,年齡(age)大於18的人:
student.objects.filter(id__gt=3,age__gt=18)
用Q對象查詢 and用Q對象中的&符號:
student.objects.filter(Q(id__gt=3)&Q(age__gt=18))
|對應or
查詢id=1或者age大於25的人:
student.objects.filter(Q(id=1)|Q(age__gt=25))
Q對象中還能進行非操作~:
查詢id不等於2的人
student.objects.filter(~Q(id=2))
F對象
多條件可以解決,那屬性之間的比較怎麼解決?
F對象
導入F對象:
from django.db.models import F
查詢id大於年齡(age)的人
student.objects.filter(id__gt=F('age'))
聚合函數
在mysql中有sum,count,avg,max,mix等聚合函數,
我們操作模型同樣可以達到效果:
導入聚合類模組
from django.db.models import Sum,Avg,Count,Max,Mix
聚合函數實例
使用聚合函數需要使用aggregate來操作
查詢所有人的數目
student.objects.all().aggregate(Count('id'))
查詢年齡(age)的和
student.objects.all().aggregate(Sum('age'))
其他就不一一實例了。
上面返回的是一個字典:
比如查詢的所有人的數目返回:
{'id__count':值}
年齡和:
{'age__sum':值}
key值是字典加雙下劃線加聚合函數的名字。
count函數
查詢所有人的數目也可以這樣寫
student.objects.all().count()
注意:當返回值類型為QuerySet類型時,我們稱他為一個查詢集,可以再次進行以上任何操作。
查詢集的特性
1、惰性查詢
只有當我們使用數據的時候,才會在mysql中去查詢。
2、快取
當我們使用同一個查詢集的時候,只有第一次是執行到資料庫,然後把結果儲存起來,當我們再次使用這個查詢集的時候,就會調用我們快取中的數據。
查詢集相當於一個列表,我們取值可以遍歷取出,也可以進行下表或者切片取出。
當我們對一個查詢集進行切片或下標查詢,會返回一個新的查詢集。
不同的是我們的切片不允許為負值。
判斷一個查詢集是否有數據。
查詢集.exists(),有返回True,沒有返回False
模型類關係
1、一對多關係
例如一個班級對應多個人
我們需要用ForeignKey()來關聯我們的模型。
2、多對多
一個老師對應多個學生,一個學生對應多個老師
那麼老師表和學生表就是多對多的關係。
我們需要使用ManyToManyField(),那麼你會說我定義在那個表裡了?定義那個表都行。
3、一對一關係
學生的學號和學生的詳細資訊表就是一對一的關係。
可以用OneToOneField來定義,定義那個一個類都可以。
關聯查詢(一對多)
關聯實例班級表(classinfo),學生表(stuinfo)
查詢班級id為1的所有學生:
# 查詢到id為1的班級
c = classinfo.objects.get(id=1)
# 利用關聯的表加__set來查詢
c.stuinfo__set.all()
反過來,查詢id為1的學生的班級名稱
# 查詢id=1的學生
s = student.objects.get(id=1)
# 直接通過關聯的欄位來查詢
s.關聯欄位,比如s.c_id
以上很麻煩,我們直接通過模型類來查詢
實例:
查詢班級表中學生的名字包含張的班級
classinfo.objects.filter(stuinfo__name__contains = '張')
你想要得到那張表,就用那張表去查詢。
查詢學生表中,班級表中id為1的學生.
# 學生表中有關聯的欄位,我們通過關聯的欄位來查詢。
stuinfo.objects.filter(c_id__id = 1)
自關聯
自關聯是一種特殊的一對多的關係,
我們在關鍵模型類的時候,需要使用ForgignKey('self'),表示關聯自己。
同樣的查詢方式。
管理器
什麼是管理器?
我們每次查詢的時候都會是模型.objects.xxx。
這個objects是Django幫我們自動生成的管理器對象。通過objects來幫助我們查詢資訊。
objects是models.Manger的一個對象,也就是說objects繼承於models.Manger。
同樣我們可以不使用Django幫我們生成的,我們可以自己創建一個。
為什麼要自己創建?
1、過濾查詢集,比如你查詢全部數據,我只讓你返回前十條。
2、添加新的方法,比如添加,修改可以封裝在裡面方面我們使用。
過濾查詢集實例
如果我們在models.py中創建一個模型:
# 創建stuinfo表
class stuinfo(model.Model):
# name 字元串類型 最大長度為20
name = mdoels.CharField(max_length=20)
# age 數字類型
age = model.IntegerField()
# 自定義一個管理器對象
# objects是我定義的一個名字,你可以定義成其他的
# stuinfoManage是我定義的管理器的類名,同樣你可以定義成其他
objects = stuinfoManage()
# 定義管理類,繼承model.Manager
class stuinfoManage(model.Manager):
# 該更返回的查詢集
# 重新定義all方法
def all(self):
# 調用父類方法中的all()查詢到全部內容
s = super().all()
# 過濾數據,只顯示id小於10的數據
s = s.filter(id__lt=10)
# 返回數據
return s
添加新的方法實例
同樣我們在上面的stuinfoManage中添加一個新方法添加
class stuinfoManage(model.Manager):
# 該更返回的查詢集
# 重新定義all方法
def all(self):
# 調用父類方法中的all()查詢到全部內容
s = super().all()
# 過濾數據,只顯示id小於10的數據
s = s.filter(id__lt=10)
# 返回數據
return s
# 添加一個添加方法
def stu_create(self,name,age):
# 實例化stuinfo類
# 這裡我們給大家介紹一個新的方法
# stuinfo.objects.model 返回的就是stuinfo
# 所以我們這個實例對象不需要s = stuinfo()了
s = self.model
s = s()
s.name = name
s.age = age
s.save()
return s
你能想到為我們的添加方法封裝,那Djang的創造者自然也想得到。
我們添加的時候需要:
不過這裡需要指定參數傳遞
student.objects.cretae(name='張三',age=18)
元選項
以上我們都是先創建好模型再去遷移,創建表,
試想,如果我們的資料庫已經存在呢?
比如我們在資料庫創建的表是stu,
我們的模型是stuinfo,我們可以給他指定一個資料庫里的表
class stuinfo(model.Model):
name = mdoels.CharField(max_length=20)
age = model.IntegerField()
# 我們需要在模型里再定義一個Meta類
class Meta:
db_table = 'stu'
即可。
orm映射的表名也即是我們在自動生成表的表名是:
應用名_類名。
所以你去修改數據的表名也是可以實現的。
另:前端知識希望自己補充.