柚子快報(bào)邀請(qǐng)碼778899分享:Django與數(shù)據(jù)庫(kù)
柚子快報(bào)邀請(qǐng)碼778899分享:Django與數(shù)據(jù)庫(kù)
目錄
創(chuàng)建項(xiàng)目app
?路由子表
數(shù)據(jù)庫(kù)
?創(chuàng)建數(shù)據(jù)庫(kù)
什么是ORM
定義數(shù)據(jù)庫(kù)表
Django Admin 管理數(shù)據(jù)
過(guò)濾條件
代碼直接生成HTML
?使用模板
前后端分離架構(gòu)
對(duì)資源的增刪改查處理
列出客戶
?添加客戶
?臨時(shí)取消 CSRF 校驗(yàn)
修改客戶信息
?刪除客戶
Django中ORM的處理
數(shù)據(jù)模型的配置
字段設(shè)置
字段參數(shù)
數(shù)據(jù)更新的實(shí)現(xiàn)
?
創(chuàng)建項(xiàng)目app
Django中的一個(gè)app就是項(xiàng)目里面的一個(gè)應(yīng)用的意思,一個(gè)項(xiàng)目包含多個(gè)app,一個(gè)app通常就是一個(gè)相對(duì)獨(dú)立的模塊,實(shí)現(xiàn)相對(duì)獨(dú)立的功能。比如我們可以把系統(tǒng)中的管理員管理的功能放在一個(gè)名為mgr的app里面,把銷售人員的操作實(shí)現(xiàn)在另一個(gè)名為sales的app里面。
Django中創(chuàng)建app可以通過(guò)執(zhí)行命令,創(chuàng)建一個(gè)app目錄,并在里面自動(dòng)創(chuàng)建app常用的文件。
進(jìn)入項(xiàng)目根目錄,執(zhí)行以下命令:
python manage.py startapp sales
這樣就會(huì)創(chuàng)建一個(gè)目錄名為 sales, 對(duì)應(yīng) 一個(gè)名為 sales 的app,里面包含了如下自動(dòng)生成的文件:?
migrations
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
?路由子表
一個(gè)請(qǐng)求對(duì)應(yīng)一個(gè)處理函數(shù),項(xiàng)目較大時(shí),請(qǐng)求的url會(huì)特別多,我們可以將不同的路由記錄按照功能分拆到不同的url路由子表中。
數(shù)據(jù)庫(kù)
后端開(kāi)發(fā)基本需要操作數(shù)據(jù),包括數(shù)據(jù)的存儲(chǔ)、查詢、修改、刪除。通常,這些都是通過(guò)數(shù)據(jù)來(lái)完成,目前業(yè)界最廣泛使用的數(shù)據(jù)庫(kù)還是:關(guān)系型數(shù)據(jù)庫(kù)。
關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng),常用的開(kāi)源數(shù)據(jù)庫(kù)有mysql和postgresql.
?創(chuàng)建數(shù)據(jù)庫(kù)
項(xiàng)目中數(shù)據(jù)庫(kù)的配置在settings.py中。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 數(shù)據(jù)庫(kù)類型
'NAME': 'core', # 所使?的數(shù)據(jù)庫(kù)的名字
'USER': 'root', # 數(shù)據(jù)庫(kù)服務(wù)器的?戶
'PASSWORD': 'xxxxxx', # 密碼
'HOST': '127.0.0.1', # 主機(jī)
'PORT': '3306', # 端?
}
}
執(zhí)行以下命令,創(chuàng)建數(shù)據(jù)庫(kù):
python manage.py migrate
?項(xiàng)目的根目錄下面生成一個(gè)配置文件中指定的數(shù)據(jù)庫(kù)文件:db.sqlite3。
并且會(huì)在其中創(chuàng)建一些表。
什么是ORM
Django里面,數(shù)據(jù)庫(kù)的操作,包括數(shù)據(jù)的增刪改查,基本都是通過(guò)Model類型的對(duì)象進(jìn)行的。
通常,在Django中:
定義一張數(shù)據(jù)庫(kù)表就是定義一個(gè)繼承自django.db.models.Model的類定義該表中的字段(列),就是定義該類里面的一些屬性類的方法就是對(duì)該表中數(shù)據(jù)的處理方法,包括數(shù)據(jù)的增刪改查
這樣,開(kāi)發(fā)者對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),從原來(lái)的使用底層的sql語(yǔ)句,變成面向?qū)ο蟮拈_(kāi)發(fā),通過(guò)一系列對(duì)象的類定義和方法調(diào)用就可以操作數(shù)據(jù)庫(kù)。
這樣做:
首先極大地簡(jiǎn)化了我們應(yīng)用中的數(shù)據(jù)庫(kù)開(kāi)發(fā),因?yàn)闊o(wú)需使用sql語(yǔ)句操作數(shù)據(jù)庫(kù)了,提高了開(kāi)發(fā)的效率。
其次屏蔽了不同的數(shù)據(jù)庫(kù)訪問(wèn)的底層細(xì)節(jié),開(kāi)發(fā)好代碼后,如果要換數(shù)據(jù)庫(kù),幾乎不需要改代碼,修改幾個(gè)配置項(xiàng)即可。
這種通過(guò)對(duì)象操作數(shù)據(jù)庫(kù)的方法被稱為ORM(object relational mapping)。
Django的ORM(對(duì)象關(guān)系映射)是一個(gè)強(qiáng)大的工具,用于在Django應(yīng)用程序中管理數(shù)據(jù)庫(kù),借助它我們可以使用Python代碼而不是編寫SQL語(yǔ)句來(lái)操作數(shù)據(jù)庫(kù),這是因?yàn)镈jango的ORM提供了一個(gè)高級(jí)的抽象層,通過(guò)定義Python類來(lái)表示數(shù)據(jù)庫(kù)表,并使用這些類來(lái)執(zhí)行常見(jiàn)的數(shù)據(jù)庫(kù)操作,如創(chuàng)建、讀取、更新和刪除數(shù)據(jù)。
定義數(shù)據(jù)庫(kù)表
我們?cè)賱?chuàng)建一個(gè)名為common的應(yīng)用目錄,里面存放我們項(xiàng)目需要的一些公共的表的定義。
執(zhí)行以下命令:
python manage.py startapp common
創(chuàng)建了一個(gè)名為common的app.
打開(kāi)common/models.py,發(fā)現(xiàn)里面是空的,因?yàn)槲覀冞€沒(méi)有定義我們的業(yè)務(wù)所需要的表。
加入以下內(nèi)容:
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=100)
phonenumber = models.CharField(max_length=100)
address = models.CharField(max_length=100)
?這個(gè)Customer類繼承自django.db.models.Model,就是用來(lái)定義數(shù)據(jù)庫(kù)表的,里面的name,phonenumber,address是該表的3個(gè)字段。
CharField對(duì)象對(duì)應(yīng)的是varchar類型的數(shù)據(jù)庫(kù)字段。定義表中的字段就是定義一些靜態(tài)屬性,這些屬性是django.db.models里面的各種Field對(duì)象,對(duì)應(yīng)不同類型的字段。
在settings.py中加入一句代碼:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sales',
# 加入以下代碼:
'common.apps.CommonConfig'
]
?'common.apps.CommonConfig' 告訴 Django,CommonConfig 是 common/apps.py 文件中定義的一個(gè)應(yīng)用配置的類。
class CommonConfig(AppConfig):
name = 'common'
CommonConfig 是 AppConfig的 子類, 就表示這個(gè)是應(yīng)用的配置類。
這里 name = 'common' , name 是用來(lái)定義 應(yīng)用的python模塊路徑的。也就是說(shuō) 應(yīng)用 模塊路徑為 common 。
?Django知道了我們的common應(yīng)用,可以在項(xiàng)目根目錄下執(zhí)行命令
python manage.py makemigrations common
得到以下結(jié)果:
Migrations for 'common':
common\migrations\0001_initial.py
- Create model Customer
會(huì)發(fā)現(xiàn)在 common\migrations 目錄下面出現(xiàn)了0001_initial.py, 這個(gè)腳本就是相應(yīng)要進(jìn)行的數(shù)據(jù)庫(kù)操作代碼。
隨即,執(zhí)行如下命令:
python manage.py migrate
查看數(shù)據(jù)庫(kù),發(fā)現(xiàn)創(chuàng)建了一張名為 common_customer的表。
多出來(lái)的 id 字段是該表的主鍵, 是Django自動(dòng)幫我們添加的。
這個(gè)不需要我們?cè)陬愔酗@式的定義。
注意:
如果以后我們修改了Models.py 里面的庫(kù)表的定義,都需要再次運(yùn)行 python manage.py makemigrations common 和 python manage.py migrate 命令,使數(shù)據(jù)庫(kù)同步該修改結(jié)果
Django Admin 管理數(shù)據(jù)
Django提供了一個(gè)管理員操作界面,可以方便地添加、修改、刪除定義的model表數(shù)據(jù)。
首先,我們需要?jiǎng)?chuàng)建一個(gè)超級(jí)管理員賬號(hào),進(jìn)入到項(xiàng)目的根目錄,執(zhí)行以下命令,依次輸入要?jiǎng)?chuàng)建的管理員的登錄名、email、密碼。
python manage.py createsuperuser
Username (leave blank to use '21544'): present
Error: That username is already taken.
Username (leave blank to use '21544'): present-01
Email address: 0123@qq.com
Password:
Password (again):
Superuser created successfully.
然后需要修改應(yīng)用里面的管理員配置文件common/admin.py,注冊(cè)我們定義的model類,這樣Django才會(huì)知道
from django.contrib import admin
from .models import Customer
admin.site.register(Customer)
?然后可以訪問(wèn)?http://127.0.0.1/admin/?,輸入剛才注冊(cè)的用戶密碼登錄。
登錄后可以看到如下界面。這里面是目前系統(tǒng)中可以修改的表。
點(diǎn)擊ADD,添加用戶之后點(diǎn)擊SAVE,使用數(shù)據(jù)庫(kù)查看工具,就發(fā)現(xiàn)數(shù)據(jù)庫(kù)中確實(shí)有了添加的數(shù)據(jù)信息:
?我們先實(shí)現(xiàn)一個(gè)函數(shù),來(lái)處理sales/customers/訪問(wèn)請(qǐng)求,返回?cái)?shù)據(jù)庫(kù)中customer表所有記錄。
Django中對(duì)數(shù)據(jù)庫(kù)表的操作,建議都是通過(guò)其對(duì)應(yīng)Model對(duì)象的方法來(lái)進(jìn)行的,而不是SQL語(yǔ)句。
比如我們要獲取customer表所有記錄,該表是和我們前面定義的Customer類管理的,我們可以這樣獲取所有表的記錄:
在文件sales/views.py中,定義一個(gè)listcustomers函數(shù),內(nèi)容如下:
# 導(dǎo)入 Customer 對(duì)象定義
from common.models import Customer
def listcustomers(request):
# 返回一個(gè) QuerySet 對(duì)象 ,包含所有的表記錄
# 每條表記錄都是是一個(gè)dict對(duì)象,
# key 是字段名,value 是 字段值
qs = Customer.objects.values()
# 定義返回字符串
retStr = ''
for customer in qs:
for name,value in customer.items():
retStr += f'{name} : {value} | '
#
表示換行
retStr += '
'
return HttpResponse(retStr)
Customer.objects.values() 會(huì)返回一個(gè) QuerySet 對(duì)象,這個(gè)對(duì)象是Django 定義的,在這里它包含所有的Customer 表記錄,QuerySet對(duì)象可以使用for循環(huán)遍歷取出里面所有的元素,每個(gè)元素對(duì)應(yīng)一條表記錄。每條表記錄元素都是一個(gè)dict對(duì)象,其中每個(gè)元素的key是表字段名,value是該記錄的字段值。上面的代碼可以將每條記錄的信息存儲(chǔ)到字符串中,返回給前端瀏覽器。
還需要修改路由表,加上對(duì)sales/customers/ url請(qǐng)求的路由。
在bysms/urls.py主路由文件中,已有以下記錄:
# 凡是 url 以 sales/ 開(kāi)頭的,
# 都根據(jù) sales.urls 里面的 子路由表進(jìn)行路由
path('sales/', include('sales.urls')),
?我們只需修改?sales/urls.py?即可,添加如下記錄:
path('customers/', views.listcustomers),
然后可以在瀏覽器輸入如下 網(wǎng)址:?http://127.0.0.1/sales/customers/
回車后,瀏覽器顯示結(jié)果類似如下:
?和我們數(shù)據(jù)庫(kù)中的記錄信息一致:
過(guò)濾條件
有的我們需要根據(jù)過(guò)濾條件查詢部分客戶信息。
比如,當(dāng)用戶在瀏覽器輸入?/sales/customers/?phonenumber=13000000001?,要求返回電話號(hào)碼為 13000000001 客戶記錄。
我們可以通過(guò)?filter?方法加入過(guò)濾條件,修改view里面的代碼,如下所示:
def listcustomers(request):
# 返回一個(gè) QuerySet 對(duì)象 ,包含所有的表記錄
qs = Customer.objects.values()
# 檢查url中是否有參數(shù)phonenumber
ph = request.GET.get('phonenumber',None)
# 如果有,添加過(guò)濾條件
if ph:
qs = qs.filter(phonenumber=ph)
# 定義返回字符串
retStr = ''
for customer in qs:
for name,value in customer.items():
retStr += f'{name} : {value} | '
#
表示換行
retStr += '
'
return HttpResponse(retStr)
Django框架在url路由匹配到函數(shù)后,調(diào)用函數(shù)時(shí),會(huì)傳入一個(gè)HttpRequest對(duì)象給參數(shù)變量request,該對(duì)象里面包含了請(qǐng)求的數(shù)據(jù)信息。
HTTP的GET請(qǐng)求url里面的參數(shù)(術(shù)語(yǔ)叫querystring里面的參數(shù)),可以通過(guò)HttpRequest對(duì)象的GET屬性獲取,這是一個(gè)類似dict的對(duì)象。
比如要獲取querystring里面的phonenumber參數(shù),就可以像這樣:
ph = request.GET.get('phonenumber',None)
第二個(gè)參數(shù)傳入None表示,如果沒(méi)有phonenumber參數(shù)在querystring中,就會(huì)返回None
然后調(diào)用QuerySet對(duì)象的filter方法,就可以把查詢過(guò)濾條件加上去
qs = qs.filter(phonenumber=ph)
有了這個(gè)過(guò)濾條件,Django 會(huì)在底層執(zhí)行數(shù)據(jù)庫(kù)查詢的SQL語(yǔ)句 加上相應(yīng)的 where 從句,進(jìn)行過(guò)濾查詢。注意,參數(shù)名 phonenumber 是和 定義的表 model 的屬性名 phonenumber 一致的。
filter的過(guò)濾條件可以有多個(gè),只要繼續(xù)在后面的參數(shù)添加過(guò)濾條件即可。
代碼直接生成HTML
HTML本身其實(shí)也是字符串,只是這個(gè)字符串里面的內(nèi)容是符合HTML語(yǔ)言規(guī)范的。
既然它也是字符串,我們可以使用Python直接構(gòu)建出 HTML 字符串內(nèi)容。
修改:
# 先定義好HTML模板
html_template ='''
id | 姓名 | 電話號(hào)碼 | 地址 |
---|
'''
def listcustomers(request):
# 返回一個(gè) QuerySet 對(duì)象 ,包含所有的表記錄
qs = Customer.objects.values()
# 檢查url中是否有參數(shù)phonenumber
ph = request.GET.get('phonenumber',None)
# 如果有,添加過(guò)濾條件
if ph:
qs = qs.filter(phonenumber=ph)
# 生成html模板中要插入的html片段內(nèi)容
tableContent = ''
for customer in qs:
tableContent += '
for name,value in customer.items():
tableContent += f'
tableContent += '
return HttpResponse(html_template%tableContent)
我們用一個(gè)變量 html_template 存儲(chǔ)html模板,代碼中生成html 里面需要插入的表格記錄的內(nèi)容,這個(gè)內(nèi)容是html片段,也就是 html 表格的每行 。
最后填入到 html_template 模板里面,就產(chǎn)生了完整的HTML 字符串。
最后返回該 html 文檔 字符串 即可。
修改后,再次訪問(wèn) http://127.0.0.1/sales/customers/
得到如下內(nèi)容:
?
?使用模板
上面我們是用Python代碼直接拼接出html內(nèi)容。
但是這種方式處理代碼比較麻煩。特別是當(dāng)html里面有多處內(nèi)容需要填入時(shí),使用Python代碼直接拼接就顯得很繁雜,不好維護(hù)。
很多后端框架都提供了一種 模板技術(shù), 可以在html 中嵌入編程語(yǔ)言代碼片段, 用模板引擎(就是一個(gè)專門處理HTML模板的庫(kù))來(lái)動(dòng)態(tài)的生成HTML代碼。
我們修改一下代碼,使用Django的模板引擎:
# 先定義好HTML模板
html_template ='''
id | 姓名 | 電話號(hào)碼 | 地址 |
---|---|---|---|
{{ value }} |
'''
from django.template import engines
django_engine = engines['django']
template = django_engine.from_string(html_template)
def listcustomers(request):
# 返回一個(gè) QuerySet 對(duì)象 ,包含所有的表記錄
qs = Customer.objects.values()
# 檢查url中是否有參數(shù)phonenumber
ph = request.GET.get('phonenumber',None)
# 如果有,添加過(guò)濾條件
if ph:
qs = qs.filter(phonenumber=ph)
# 傳入渲染模板需要的參數(shù)
rendered = template.render({'customers':qs})
return HttpResponse(rendered)
然后,訪問(wèn)瀏覽器,可以得到一樣的結(jié)果。
對(duì)比 Python直接產(chǎn)生 HTML,可以發(fā)現(xiàn)使用模板引擎的好處,就是產(chǎn)生HTML的代碼更簡(jiǎn)單方便了。
因?yàn)槲覀兛梢灾苯影岩傻?HTML片段 寫在 HTML模板 里面。
然后,只需要傳入渲染模板所需要的參數(shù)就可以了,模板引擎會(huì)自動(dòng)化幫我們生成HTML
前后端分離架構(gòu)
?界面完全交給前端開(kāi)發(fā)人員去做, 后端開(kāi)發(fā)只需要提供前端界面所需要的數(shù)據(jù)即可。
前端和后端之間的交互就完全是業(yè)務(wù)處理了,需要定義好前端和后端交互數(shù)據(jù)的接口
目前通常這樣的接口設(shè)計(jì)最普遍的就是使用REST風(fēng)格的API接口。
前端通過(guò)API接口從后端獲取數(shù)據(jù)展示在界面上,也通過(guò)API接口告訴后端需要更新的數(shù)據(jù)是什么。
通常前后端的API接口是由架構(gòu)師設(shè)計(jì)的,有時(shí)也可以由經(jīng)驗(yàn)豐富的前端開(kāi)發(fā)者或者后端開(kāi)發(fā)者設(shè)計(jì)。
對(duì)資源的增刪改查處理
前面我們已經(jīng)為?銷售員用戶?專門創(chuàng)建了一個(gè)應(yīng)用 sales 來(lái)處理相關(guān)的 請(qǐng)求,我們可以 再為?管理員用戶?專門創(chuàng)建一個(gè)應(yīng)用 mgr 來(lái)處理相關(guān)的 請(qǐng)求。
執(zhí)行以下命令:
python manage.py startapp mgr
我們可以發(fā)現(xiàn)對(duì)資源的增刪改查 操作, 都是同一個(gè)URL,都是?/api/mgr/customers?。
而且我們發(fā)現(xiàn),不同的操作請(qǐng)求,使用不同的 HTTP 請(qǐng)求方法 ,比如 添加是POST, 查詢是 GET, 修改是 PUT, 刪除是 DELETE。
而且請(qǐng)求的參數(shù)中都有 action 參數(shù)表明這次請(qǐng)求的操作具體是什么。
注意:Django 的 url路由功能?不支持?根據(jù) HTTP 請(qǐng)求的方法 和請(qǐng)求體里面的參數(shù) 進(jìn)行路由。
就是不能像下面這樣,來(lái)根據(jù)請(qǐng)求 是 post 還是 get 來(lái) 路由:
path('customers/', 'app.views.list_customer', method='get'),
path('customers/', 'app.views.add_customer', method='post'),
有一種方式是:自己編寫一個(gè)函數(shù), 來(lái) 根據(jù) http請(qǐng)求的類型 和請(qǐng)求體里面的參數(shù) 分發(fā)(或者說(shuō)路由)給 不同的函數(shù)進(jìn)行處理。
我們可以 在 customer.py 中定義如下 dispatcher 函數(shù):
def dispatcher(request):
# 將請(qǐng)求參數(shù)統(tǒng)一放入request 的 params 屬性中,方便后續(xù)處理
# GET請(qǐng)求 參數(shù)在url中,同過(guò)request 對(duì)象的 GET屬性獲取
if request.method == 'GET':
request.params = request.GET
# POST/PUT/DELETE 請(qǐng)求 參數(shù) 從 request 對(duì)象的 body 屬性中獲取
elif request.method in ['POST','PUT','DELETE']:
# 根據(jù)接口,POST/PUT/DELETE 請(qǐng)求的消息體都是 json格式
request.params = json.loads(request.body)
# 根據(jù)不同的action分派給不同的函數(shù)進(jìn)行處理
action = request.params['action']
if action == 'list_customer':
return listcustomers(request)
elif action == 'add_customer':
return addcustomer(request)
elif action == 'modify_customer':
return modifycustomer(request)
elif action == 'del_customer':
return deletecustomer(request)
else:
return JsonResponse({'ret': 1, 'msg': '不支持該類型http請(qǐng)求'})
該函數(shù) 把 請(qǐng)求消息中的參數(shù)統(tǒng)一放入到 request請(qǐng)求對(duì)象的params 屬性中。
params 屬性 被 做成一個(gè) dict 類型 , 方便后面的處理函數(shù)來(lái)獲取消息中的參數(shù)。
然后 dispatch函數(shù)再根據(jù) 請(qǐng)求的 類型 和 action 參數(shù)的值 決定由那個(gè)函數(shù)具體處理該請(qǐng)求消息。
比如 action 參數(shù) 為 'add_customer' 的 請(qǐng)求 就由 addcustomer 函數(shù) 進(jìn)行處理。
當(dāng)然在文件的開(kāi)頭,我們需要 先導(dǎo)入 JsonResponse 和 json 的定義,像下面這樣:
from django.http import JsonResponse
import json
接下來(lái),根據(jù) API 接口 ,我們發(fā)現(xiàn) 凡是 API 請(qǐng)求url為?/api/mgr/customers?的,都屬于 客戶 相關(guān)的API, 都應(yīng)該交由 我們上面定義的dispatch函數(shù)進(jìn)行分派處理。
那么我們需要在Django的url路由文件中加入對(duì)應(yīng)的路由
第一步:我們應(yīng)該在 總路由文件?bysms/urls.py?中定義了如下部分:
# 凡是 url 以 api/mgr 開(kāi)頭的,
# 都根據(jù) mgr.urls 里面的 子路由表進(jìn)行路由
path('api/mgr/', include('mgr.urls')),
?第二步: 在 mgr 目錄下面添加 urls.py 路由文件, 并 加入如下聲明即可, 如下所示:
from django.urls import path
from mgr import customer
urlpatterns = [
path('customers', customer.dispatcher),
]
這樣,就表示 凡是 API 請(qǐng)求url為?/api/mgr/customers?的,都交由 我們上面定義的dispatch函數(shù)進(jìn)行分派處理?。
列出客戶
根據(jù)接口文檔,列出客戶數(shù)據(jù)接口,后端返回的數(shù)據(jù)格式如下:
{
"ret": 0,
"retlist": [
{
"address": "江蘇省常州武進(jìn)市白云街44號(hào)",
"id": 1,
"name": "武進(jìn)市 袁騰飛",
"phonenumber": "13886666666"
},
{
"address": "北京海淀區(qū)",
"id": 4,
"name": "北京海淀區(qū)代理 蔡國(guó)慶",
"phonenumber": "13990123456"
}
]
}
這里我們無(wú)需 將數(shù)據(jù)庫(kù)中獲取的數(shù)據(jù) 轉(zhuǎn)化為 供瀏覽器展示的HTML。
在前后端分離的開(kāi)發(fā)架構(gòu)中,如何展示數(shù)據(jù)是前端的事情。后端只需要根據(jù)接口文檔, 返回原始數(shù)據(jù)即可。
我們可以使用如下的函數(shù)來(lái)返回?cái)?shù)據(jù)庫(kù)的所有的 客戶數(shù)據(jù)信息
def listcustomers(request):
# 返回一個(gè) QuerySet 對(duì)象 ,包含所有的表記錄
qs = Customer.objects.values()
# 將 QuerySet 對(duì)象 轉(zhuǎn)化為 list 類型
# 否則不能 被 轉(zhuǎn)化為 JSON 字符串
retlist = list(qs)
return JsonResponse({'ret': 0, 'retlist': retlist})
當(dāng)然在文件的開(kāi)頭,我們需要 先導(dǎo)入 Customer 定義,像下面這樣:
# 導(dǎo)入 Customer
from common.models import Customer
?添加客戶
根據(jù)接口文檔,添加客戶數(shù)據(jù)接口,前端提供的客戶數(shù)據(jù)格式如:
{
"action":"add_customer",
"data":{
"name":"武漢市橋西醫(yī)院",
"phonenumber":"13345679934",
"address":"武漢市橋西醫(yī)院北路"
}
}
我們可以使用如下的函數(shù)來(lái)處理:
def addcustomer(request):
info = request.params['data']
# 從請(qǐng)求消息中 獲取要添加客戶的信息
# 并且插入到數(shù)據(jù)庫(kù)中
# 返回值 就是對(duì)應(yīng)插入記錄的對(duì)象
record = Customer.objects.create(name=info['name'] ,
phonenumber=info['phonenumber'] ,
address=info['address'])
return JsonResponse({'ret': 0, 'id':record.id})
Customer.objects.create?方法就可以添加一條Customer表里面的記錄。?
?臨時(shí)取消 CSRF 校驗(yàn)
根據(jù)接口文檔,添加客戶 請(qǐng)求是個(gè)Post請(qǐng)求
POST /網(wǎng)站名/api/mgr/signin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
注意,新創(chuàng)建的項(xiàng)目, Django 缺省會(huì)啟用一個(gè) CSRF (跨站請(qǐng)求偽造) 安全防護(hù)機(jī)制。
在這種情況下, 所有的Post、PUT 類型的 請(qǐng)求都必須在HTTP請(qǐng)求頭中攜帶用于校驗(yàn)的數(shù)據(jù)。
為了簡(jiǎn)單起見(jiàn),我們先臨時(shí)取消掉CSRF的 校驗(yàn)機(jī)制,等以后有需要再打開(kāi)。
要臨時(shí)取消掉CSRF的 校驗(yàn)機(jī)制,非常簡(jiǎn)單,只需要在 項(xiàng)目的配置文件?bysms/settings.py?中?MIDDLEWARE?配置項(xiàng) 里 注釋掉 'django.middleware.csrf.CsrfViewMiddleware' 即可。
如下所示:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
修改客戶信息
?根據(jù)接口文檔,修改客戶數(shù)據(jù)接口,前端提供的數(shù)據(jù)格式如下:
{
"action":"modify_customer",
"id": 6,
"newdata":{
"name":"武漢市橋北醫(yī)院",
"phonenumber":"13345678888",
"address":"武漢市橋北醫(yī)院北路"
}
}
我們可以使用如下的函數(shù)來(lái)處理:
def modifycustomer(request):
# 從請(qǐng)求消息中 獲取修改客戶的信息
# 找到該客戶,并且進(jìn)行修改操作
customerid = request.params['id']
newdata = request.params['newdata']
try:
# 根據(jù) id 從數(shù)據(jù)庫(kù)中找到相應(yīng)的客戶記錄
customer = Customer.objects.get(id=customerid)
except Customer.DoesNotExist:
return {
'ret': 1,
'msg': f'id 為`{customerid}`的客戶不存在'
}
if 'name' in newdata:
customer.name = newdata['name']
if 'phonenumber' in newdata:
customer.phonenumber = newdata['phonenumber']
if 'address' in newdata:
customer.address = newdata['address']
# 注意,一定要執(zhí)行save才能將修改信息保存到數(shù)據(jù)庫(kù)
customer.save()
return JsonResponse({'ret': 0})
?刪除客戶
根據(jù)接口文檔,刪除客戶數(shù)據(jù)接口,前端只需要提供要?jiǎng)h除的客戶的ID。
數(shù)據(jù)格式如下:
{
"action":"del_customer",
"id": 6
}
我們可以使用如下的函數(shù)來(lái)處理:
def deletecustomer(request):
customerid = request.params['id']
try:
# 根據(jù) id 從數(shù)據(jù)庫(kù)中找到相應(yīng)的客戶記錄
customer = Customer.objects.get(id=customerid)
except Customer.DoesNotExist:
return {
'ret': 1,
'msg': f'id 為`{customerid}`的客戶不存在'
}
# delete 方法就將該記錄從數(shù)據(jù)庫(kù)中刪除了
customer.delete()
return JsonResponse({'ret': 0})
Django中ORM的處理
模型(Models):核心組件,一個(gè)模型類代表了一個(gè)數(shù)據(jù)庫(kù)表,而類的屬性則對(duì)應(yīng)著表的字段
字段(Fields):模型類的屬性通常被稱為字段,各種字段類型在定義模型類中的屬性和數(shù)據(jù)庫(kù)表中的字段
查詢集(QuerySets):數(shù)據(jù)庫(kù)查詢的方法,允許以鏈?zhǔn)椒绞綐?gòu)建復(fù)雜的查詢,過(guò)濾、排序和限制結(jié)果集等操作
關(guān)聯(lián)(Relations):定義模型之間的關(guān)聯(lián)關(guān)系,關(guān)系使得進(jìn)行數(shù)據(jù)查詢和操作變得更加容易
遷移(Migrations):用于管理數(shù)據(jù)庫(kù)模式的變化,更改模型定義時(shí),可以使用遷移工具自動(dòng)更新數(shù)據(jù)庫(kù)表結(jié)構(gòu),而無(wú)需手動(dòng)編寫SQL語(yǔ)句
數(shù)據(jù)模型的配置
字段設(shè)置
AutoField:自增
IntegerField:整數(shù)字段,用于存儲(chǔ)整數(shù)值
FloatField:浮點(diǎn)字段,存儲(chǔ)小叔數(shù)值
CharField:字符字段,用于存儲(chǔ)字符串
TextField:文本字段,用于存儲(chǔ)長(zhǎng)文本
字段參數(shù)
max_length:針對(duì)字符串或者長(zhǎng)文本指定字段的最大長(zhǎng)度
default:指定字段的默認(rèn)值
null:設(shè)置字段是否允許為null
db_column:設(shè)置列的別名
on_delete:在外鍵設(shè)置中指定在關(guān)聯(lián)的對(duì)象被刪除時(shí)的處理方式
models.py中的代碼:
from django.db import models
# Create your models here.
# 學(xué)校信息
class School(models.Model):
id = models.AutoField('記錄編號(hào)', primary_key=True) # 主鍵
name = models.CharField('學(xué)校名稱', max_length=32, null=False)
address = models.CharField('學(xué)校地址', max_length=200)
class Meta:
db_table = 'father_school' # 表名
# 校長(zhǎng)信息
class Principal(models.Model):
id = models.AutoField('記錄編號(hào)', primary_key=True) # 主鍵
name = models.CharField('校長(zhǎng)名稱', max_length=20, null=False)
school = models.OneToOneField(School, on_delete=models.CASCADE, db_column="school_id")
class Meta:
db_table = 'father_principal' # 表名
# 院系信息
class Department(models.Model):
id = models.AutoField('記錄編號(hào)', primary_key=True) # 主鍵
name = models.CharField('院系名稱', max_length=32, null=False)
school = models.ForeignKey(School, on_delete=models.CASCADE, db_column="school_id")
class Meta:
db_table = 'father_department' # 表名
# 授課教師
class Teacher(models.Model):
id = models.AutoField('記錄編號(hào)', primary_key=True) # 主鍵
name = models.CharField('教師名稱', max_length=20, null=False)
Department = models.ForeignKey(Department, on_delete=models.CASCADE, db_column="department_id")
class Meta:
db_table = 'father_teacher' # 表名
# 學(xué)生信息
class Student(models.Model):
id = models.AutoField('記錄編號(hào)', primary_key=True) # 主鍵
name = models.CharField('學(xué)生名稱', max_length=20, null=False)
gender = models.CharField('學(xué)生性別', default='男', max_length=2, null=False)
age = models.IntegerField('學(xué)生年齡', default=18, null=False)
school = models.ForeignKey(School, on_delete=models.CASCADE, db_column="school_id")
Teacher = models.ManyToManyField(Department, db_column="student_id")
class Meta:
db_table = 'father_student' # 表名
數(shù)據(jù)更新的實(shí)現(xiàn)
添加信息:
insert into 表名(列名列表) values(值列表)
修改信息:
update 表名 set 列名=值... where 修改條件
刪除信息:
delete from 表名 where 修改條件
柚子快報(bào)邀請(qǐng)碼778899分享:Django與數(shù)據(jù)庫(kù)
文章來(lái)源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。