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映射的表名也即是我們在自動生成表的表名是:

應用名_類名。

所以你去修改數據的表名也是可以實現的。

另:前端知識希望自己補充.