零基礎(chǔ)入手Django(六):模型基礎(chǔ)1
滴水石穿,繩鋸木斷~學(xué)習(xí)貴在持之以恒!

今天是2019年1月19日,小叮當(dāng)繼續(xù)為大家分享Django干貨。主要內(nèi)容有:Django的ORM簡(jiǎn)介、數(shù)據(jù)庫(kù)連接配置、模型的創(chuàng)建與映射、數(shù)據(jù)的增刪改查。

一、Django的ORM簡(jiǎn)介
1.ORM
ORM的全稱(chēng)是Object Relational Mapping翻譯過(guò)來(lái)就是對(duì)象關(guān)系映射的意思。
2.ORM的優(yōu)勢(shì)
不用直接編寫(xiě)SQL代碼,只需像操作對(duì)象一樣從數(shù)據(jù)庫(kù)操作數(shù)據(jù)。

3.django模型映射關(guān)系
django中模型類(lèi)、類(lèi)屬性和數(shù)據(jù)庫(kù)的對(duì)應(yīng)關(guān)系如下:

(1)模型類(lèi)必須都寫(xiě)在app下的models.py文件中。
(2)模型如果需要映射到數(shù)據(jù)庫(kù),所在的app必須被安裝.
(3)一個(gè)數(shù)據(jù)表對(duì)應(yīng)一個(gè)模型類(lèi),表中的字段,對(duì)應(yīng)模型中的類(lèi)屬性.
二、數(shù)據(jù)庫(kù)連接配置
準(zhǔn)備工作
(1)在項(xiàng)目的主目錄下找到settings.py文件中的“DATABASES"

其中”?ENGINE“表示存儲(chǔ)引擎,默認(rèn)連接的是”sqlite3"數(shù)據(jù)庫(kù)。“sqlite3"是Django中自帶的一個(gè)小巧數(shù)據(jù)庫(kù)。
我們以常使用mysql數(shù)據(jù)庫(kù)為例說(shuō)明:
(2)將默認(rèn)的”DATABASES"注釋掉

(3)在xshell中使用命令進(jìn)入mysql
用戶(hù)名密碼如下

如上使用root用戶(hù)后,輸入密碼qwe123即可進(jìn)入mysql

(4)建立新的數(shù)據(jù)庫(kù)管理用戶(hù)
創(chuàng)建一個(gè)管理員用戶(hù)xdd(小叮當(dāng))賬號(hào),密碼為xdd:
給這個(gè)"xdd"用戶(hù)授予所有遠(yuǎn)程訪(fǎng)問(wèn),這個(gè)用戶(hù)主要用于管理整個(gè)數(shù)據(jù)庫(kù),備份,還原等操作。
使授權(quán)立即生效:
操作如下

(5)查看當(dāng)前數(shù)據(jù)庫(kù),并新建數(shù)據(jù)庫(kù)用于django項(xiàng)目
使用命令查看數(shù)據(jù)庫(kù)
查看結(jié)果

新建數(shù)據(jù)庫(kù),名為“mydb”
結(jié)果如下:

2.配置數(shù)據(jù)庫(kù)連接
(1)在主目錄的settings.py中寫(xiě)入如下連接代碼:
如下圖所示

3.pymysql數(shù)據(jù)庫(kù)連接器配置
使用“exit"退出mysql

”在我們的django虛擬環(huán)境中安裝pymysql
(1)進(jìn)入項(xiàng)目虛擬環(huán)境查看是否裝有pymysql
查看當(dāng)前虛擬環(huán)境
進(jìn)入項(xiàng)目虛擬環(huán)境
查看當(dāng)前安裝包
結(jié)果如下

(2)如果沒(méi)有pymysql使用命令安裝pymysql
安裝pymysql
如下

(3)配置pymysql(因?yàn)閐jango默認(rèn)的配置不是pymysql)
在主目錄的“_init_py”中寫(xiě)入如下代碼
如下

這時(shí)pymysql下可能會(huì)有“紅波浪線(xiàn)”提示

我們點(diǎn)擊pycharm中的file----settings----project interpreter 查看,只要確認(rèn)我們配置的遠(yuǎn)程解釋器中已安裝pymysql即可。

三、模型的創(chuàng)建與映射
1.新建測(cè)試app
(1)在pycharm的“tool"中找到”Run manage.py Task...“

(2)使用命令新建app名為model_test
命令為:
結(jié)果如下

(3)在項(xiàng)目文件夾”hello_django“處右鍵,使用deployment進(jìn)行download下載。

執(zhí)行完畢后即可發(fā)現(xiàn)我們新建的"model_test"
(4)在主目錄“settings.py"中注冊(cè)app
在INSTALLED_APPS列表中添加”model_test“

2.創(chuàng)建類(lèi)
我們?cè)趍ode_test下找到models.py創(chuàng)建user類(lèi)(數(shù)據(jù)表)
3.生成映射文件
(1)方法一:在linux系統(tǒng)對(duì)應(yīng)項(xiàng)目目錄中執(zhí)行命令
(2)方法二:在pycharm中執(zhí)行

值得注意,如果makemigrations命令后面不加app的名字,系統(tǒng)默認(rèn)為所有app生成映射文件。
我們執(zhí)行”deployment"中的“download"進(jìn)行代碼同步后,查看model_test下的migrations文件夾即可看到我們生成的”0001_intial.py“映射文件。

4.將映射文件數(shù)據(jù)提交到數(shù)據(jù)庫(kù)
(1)方法一:在linux系統(tǒng)對(duì)應(yīng)項(xiàng)目目錄中執(zhí)行命令
(2)方法二:在pycharm中執(zhí)行

同樣,migrate命令后不跟app的名字時(shí),系統(tǒng)默認(rèn)為全部app做數(shù)據(jù)庫(kù)的映射。
5.在服務(wù)器端登錄數(shù)據(jù)庫(kù)進(jìn)行查看
使用我們創(chuàng)建的xdd用戶(hù)進(jìn)行登錄mysql
輸入密碼xdd后,使用我們連接到django項(xiàng)目的mydb數(shù)據(jù)庫(kù)
查看表格
結(jié)果如下

可以看到系統(tǒng)為我們創(chuàng)建的表“model_test_user"
值得注意的是,其命名規(guī)則為:app名字+下劃線(xiàn)+類(lèi)名的小寫(xiě)
在本例中,我們的app名字為model_test?我們創(chuàng)建的類(lèi)名為User
所以系統(tǒng)為我們創(chuàng)建了名字為”model_test_user"的表。
四、數(shù)據(jù)的增刪改查
前言
使用Djiango對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查時(shí),我們需要了解一下數(shù)據(jù)庫(kù)相關(guān)的接口(QuerySet API)
①?gòu)臄?shù)據(jù)庫(kù)中查詢(xún)出來(lái)的結(jié)果一般是一個(gè)集合,這個(gè)集合叫做 QuerySet.
②QuerySet是可迭代對(duì)象.
③.QuerySet支持切片, 不支持負(fù)索引.
④可以用list強(qiáng)行將QuerySet變成列表.
1.環(huán)境配置
(1)在model_test下的views.py中導(dǎo)入我們定義好的user類(lèi)并定義好增刪改查的視圖函數(shù)框架(用pass代替函數(shù)體)

代碼如下:
(2)在model_test下新建urls.py,在主目錄中的urls.py中為model_test分配路由。
在model_test下新建urls.py

在主目錄中為model_test分配路由

代碼如下
(3)在mode_test下的urls.py中配置分路由
#!/usr/bin/env?python
#?-*-?coding:utf-8?-*-??
__author__?=?'IT小叮當(dāng)'
__time__?=?'2019-01-22?20:00'
from?django.contrib?import?admin
from?django.urls?import?path,re_path,include
from?.?import?views
urlpatterns?=?[
????path('add/',views.add_user),
????path('delete/',views.delete_user),
????path('update/',views.update_user),
????path('search/',views.search_user),
????]
3.編寫(xiě)添加數(shù)據(jù)視圖函數(shù)
方法一:實(shí)例化類(lèi)進(jìn)行傳參
(1)在視圖函數(shù)中重新定義add_user
def?add_user(request):
????#方法一
????xdd?=?User(name='xdd',age=18)
????xdd.save()
????return?HttpResponse('小叮當(dāng)插入數(shù)據(jù)成功!')
(2)在瀏覽器中訪(fǎng)問(wèn)

(3)xshell連接服務(wù)端查看mysql

方法二:先實(shí)例化類(lèi)后傳參
(1)在視圖函數(shù)中重新定義add_user
def?add_user(request):
????#方法二
????xdd=User()
????xdd.name?=?'小叮當(dāng)'
????xdd.age?=?18
????xdd.save()
????return?HttpResponse('小叮當(dāng)使用方法二插入數(shù)據(jù)成功!')
(2)在瀏覽器中訪(fǎng)問(wèn)

(3)xshell連接服務(wù)端查看mysql

方法三:使用objects.create傳參
(1)在視圖函數(shù)中重新定義add_user
def?add_user(request):
????#方法三
????User.objects.create(name='老叮當(dāng)',age=19)
????return?HttpResponse('小叮當(dāng)使用方法三插入數(shù)據(jù)成功!')
(2)在瀏覽器中訪(fǎng)問(wèn)

(3)xshell連接服務(wù)端查看mysql

值得注意,當(dāng)我們?cè)俅嗡⑿绿砑訑?shù)據(jù)頁(yè)面后,查看mysql,發(fā)現(xiàn)數(shù)據(jù)已然重復(fù)~

刷新后,查看mysql

那么,怎樣才能在刷新頁(yè)面的同時(shí),不會(huì)造成數(shù)據(jù)庫(kù)的重復(fù)添加呢?下面,我們來(lái)看方法四~
方法四:使用objects.get_or_create()傳參
(1)在視圖函數(shù)中重新定義add_user
def?add_user(request):
????#方法四
????User.objects.get_or_create(name='小小叮當(dāng)',age=17)
????return?HttpResponse('小叮當(dāng)使用方法四插入數(shù)據(jù)成功!')
(2)在瀏覽器中訪(fǎng)問(wèn)

(3)xshell連接服務(wù)端查看mysql

再次刷新網(wǎng)頁(yè)

查看mysql

可以看到,使用方法四get_or_create()傳參新增的數(shù)據(jù)不會(huì)出現(xiàn)重復(fù)。
4.查詢(xún)數(shù)據(jù)
由于更改和刪除操作都是建立在查詢(xún)的基礎(chǔ)上,所以我們先來(lái)了解在django中如何查詢(xún)數(shù)據(jù)。
查詢(xún)所有?objects.all()
(1)在視圖函數(shù)中重新定義search_user
def?search_user(request):
????#查詢(xún)所有數(shù)據(jù)
????all_info?=?User.objects.all()
????return?HttpResponse(all_info)
(2)在瀏覽器中訪(fǎng)問(wèn)

這時(shí),我們發(fā)現(xiàn)瀏覽器中出現(xiàn)了5個(gè)用戶(hù)對(duì)象,但好像什么都看不出來(lái)!這就需要我們?cè)赨ser類(lèi)中,重新定義輸出方法了。
(3)在models.py里的User類(lèi)中,重新定義輸出方法__str__
class?User(models.Model):
????#配置id字段,設(shè)置為自增長(zhǎng),并設(shè)為主鍵(也可省略,使用系統(tǒng)默認(rèn)設(shè)置的id)
????id?=?models.AutoField(primary_key=True)
????#配置name字段,設(shè)置為字符類(lèi)型,最大長(zhǎng)度為50
????name?=?models.CharField(max_length=50)
????#配置age字段,設(shè)置為整數(shù)類(lèi)型
????age?=?models.IntegerField(max_length=50)
????#定義輸出
????def?__str__(self):
????????return?'User<id=%s,name=%s,age=%s>'%(self.id,self.name,self.age)
(4)在瀏覽器中查看

這次變成了5個(gè)連續(xù)的User,也不是我們想要看到的結(jié)果?。∵@是因?yàn)開(kāi)_str__()方法(注意str前后是兩個(gè)下橫線(xiàn))對(duì)print有效。
我們?cè)谝晥D函數(shù)中,加入print語(yǔ)句在后臺(tái)查看,
#查詢(xún)數(shù)據(jù)
def?search_user(request):
????#查詢(xún)所有數(shù)據(jù)
????all_info?=?User.objects.all()
????print(all_info)
????return?HttpResponse(all_info)
在后臺(tái)查看如下

可以看到,此時(shí)已經(jīng)可以輸出我們想要查詢(xún)的結(jié)果了。
條件查詢(xún) objects.filter()
(1)定義視圖函數(shù)
def?search_user(request):
????#查詢(xún)所有數(shù)據(jù)
????#?all_info?=?User.objects.all()
????#?print(all_info)
????#?查詢(xún)滿(mǎn)足條件
????meet_info?=?User.objects.filter(name='小叮當(dāng)')
????print(meet_info)
????return?HttpResponse(meet_info)
(2)瀏覽器中查看

(3)后臺(tái)查看

定義視圖函數(shù),對(duì)比輸出
def search_user(request):
? ?#查詢(xún)所有數(shù)據(jù)
? ?all_info = User.objects.all()
? ?# print(all_info)
? ?# 查詢(xún)滿(mǎn)足條件
? ?meet_info = User.objects.filter(name='小叮當(dāng)') ?#QuerSet
? ?print('我是查詢(xún)到的所有QuerSset',all_info)
? ?print('我是一條數(shù)據(jù)',meet_info[0]) ?#一個(gè)模型類(lèi)的實(shí)例對(duì)象----數(shù)據(jù)表的一條數(shù)據(jù)
? ?return HttpResponse(meet_info)
在瀏覽器端刷新后,再次在后臺(tái)查看

條件查詢(xún) objects.get()
定義視圖函數(shù)
#查詢(xún)數(shù)據(jù)
def?search_user(request):
????meet_info?=?User.objects.get(id=3)
????print('我通過(guò)get方法得到',meet_info)
????return?HttpResponse(meet_info)
瀏覽器中刷新后,在后臺(tái)查看

值得注意,使用objects.get()方法進(jìn)行查詢(xún)時(shí),查詢(xún)的條件需要確保“唯一性”,例如id等字段。
5.更新數(shù)據(jù)
更新數(shù)據(jù)的思路就是:先查找到數(shù)據(jù),再進(jìn)行更新操作
方法一:get()方法找到數(shù)據(jù),再屬性賦值修改后保存
(1)定義視圖函數(shù)
#更改數(shù)據(jù)
def?update_user(request):
????meet_info?=?User.objects.get(id=3)
????meet_info.name='不老叮當(dāng)'
????meet_info.save()
????return?HttpResponse('我將老叮當(dāng)改為了,不老叮當(dāng)!')
(2)瀏覽器中查看

(3)在xshell中查看數(shù)據(jù)庫(kù)

可以看到,id為3的老叮當(dāng),已經(jīng)被成功修改為不老叮當(dāng)~
方法二:使用filter()查詢(xún)數(shù)據(jù),用其自帶的update()方法進(jìn)行數(shù)據(jù)更新
(1)定義視圖函數(shù)
#更改數(shù)據(jù)
def?update_user(request):
????User.objects.filter(name='不老叮當(dāng)').update(name='神仙小叮當(dāng)')
????return?HttpResponse('我將不老叮當(dāng)改成了神仙小叮當(dāng)!')
(2)瀏覽器中查看

(3)xshell查看服務(wù)端數(shù)據(jù)庫(kù)

可以看到,“不老叮當(dāng)”已經(jīng)被成功改為“神仙小叮當(dāng)”了。
添加新的字段
當(dāng)我們想要為數(shù)據(jù)表添加新的字段時(shí),在models.py中的模型類(lèi)中添加即可。需要注意的是,添加字段會(huì)改變表的結(jié)構(gòu),因此需要重新生成映射文件,將映射文件提交到數(shù)據(jù)庫(kù)。
(1)在模型類(lèi)中添加新字段
class?User(models.Model):
????#配置id字段,設(shè)置為自增長(zhǎng),并設(shè)為主鍵(也可省略,使用系統(tǒng)默認(rèn)設(shè)置的id)
????id?=?models.AutoField(primary_key=True)
????#配置name字段,設(shè)置為字符類(lèi)型,最大長(zhǎng)度為50
????name?=?models.CharField(max_length=50)
????#配置age字段,設(shè)置為整數(shù)類(lèi)型
????age?=?models.IntegerField(max_length=50)
????#添加新字段,一定要設(shè)置最大長(zhǎng)度和默認(rèn)值
????city?=?models.CharField(max_length=50,default='洛陽(yáng)')
????#定義輸出
????def?__str__(self):
????????return?'User<id=%s,name=%s,age=%s>'%(self.id,self.name,self.age)
(2)生成映射文件
在tools中找到“Run manage.py Task"

執(zhí)行命令makemigrations model_test


可以看到,city字段已被添加到user模型類(lèi)中。
(3)將映射文件提交到數(shù)據(jù)庫(kù)
執(zhí)行命令migrate model_test


可以看到,city字段已經(jīng)添加完成。
(4)在xshell中查看數(shù)據(jù)庫(kù)

可以看到city字段已經(jīng)添加成功。
將某個(gè)字段的值全部修改為特定值
例如,我們將city中的”洛陽(yáng)“全部修改為”北京“
(1)定義視圖函數(shù)
def?update_user(request):
????User.objects.all().update(city='北京')
????return?HttpResponse('我將所有的city屬性全改為了北京!')
(2)在瀏覽器中查看

(3)通過(guò)xshell查看服務(wù)器端的數(shù)據(jù)庫(kù)

可以看到,所有city字段已更改為了”北京“。
6.刪除數(shù)據(jù)
方法一:通過(guò)objects.get().delete()來(lái)刪除數(shù)據(jù)
(1)定義視圖函數(shù)
#刪除數(shù)據(jù)
def?delete_user(request):
????User.objects.get(id=4).delete()
????return?HttpResponse('我刪除了id=4的數(shù)據(jù)!')
(2)瀏覽器中查看

(3)通過(guò)xshell在服務(wù)端查看數(shù)據(jù)庫(kù)

方法二:通過(guò)objects.filter().delete()來(lái)刪除數(shù)據(jù)
(1)定義視圖函數(shù)
#刪除數(shù)據(jù)
def?delete_user(request):
????#?User.objects.get(id=4).delete()
????User.objects.filter(name='小小叮當(dāng)').delete()
????return?HttpResponse('我刪除name為小小叮當(dāng)?shù)臄?shù)據(jù)!')
(2)瀏覽器中查看

(3)xshell中查看服務(wù)端數(shù)據(jù)庫(kù)

可以看到名為“小小叮當(dāng)”的數(shù)據(jù)已被我們成功刪除~