Python Django 學習紀錄(四) 資料庫及後台管理
一、Django 與資料庫:
Django 預設 以Model 方式操作資料庫,以 class 類別建立 Model,再透過 Model 操作資料庫和資料表,之後要更改資料庫系統,只要更改 Model 的定義即可。
1.使用 Django 資料庫:
- 使用 Django 資料庫要先進行以下步驟:
- 在 <model.py> 檔中定義class類別,每個類別相當於一個資料表
- 在 class 類別中定義變數,每一個變數相當於一個資料表欄位
- 以「 python manage.py makemigrations app名稱」或 「 python manage.py makemigrations 」來建立資料庫和 Django的中介檔
- 以 「 python manage.py migrate」同步更新資料庫內容
- 在 Python程式中存取資料庫
1.定義資料模型:
接下來將直接專案實作:
1.建立一個名為students的專案,接著建立名為studentsapp的app,在<settings.py>註冊App
創建templates目錄、static目錄、migration資料檔,利用migrate將模型與資料庫同步。
2.記得要在 <setting.py>進行整個專案的環境設定,前面幾個專案已經設定過許多次,這裡將不再說明。
3.接著在 <urls.py>定義以下自訂函式:
先將還不會用到的路徑註解掉,之後再陸續打開,以免之後設定會產生錯誤
from django.contrib import admin from django.urls import path from studentsapp import views urlpatterns = [ path('admin/', admin.site.urls), # path('listone/',views.listone), # path('listall',views.listall), # path('',views.index), # path('index',views.index), ]
(1)建立資料模型
請開啟 studentsapp專案下的 <models.py> 檔,該檔預設已經import model套件。
建立 students 類別,建立的類別必須以「class student(model.Model)」繼承model.Model,然後在student類別建立欄位:
from django.db import models class student(models.Model): cName = models.CharField(max_length=20, null=False) #建立字串型別的欄位,最大長度為20字元,欄位不可空白 cSex = models.CharField(max_length=2, default='M', null=False) #default='M',設定預設值為'M' cBirthday = models.DateField(null=False) cEmail = models.EmailField(max_length=100,blank=True, default='')#blank=True 欄位可空白 cPhone = models.CharField(max_length=50,blank=True, default='') cAddr = models.CharField(max_length=255,blank=True, default='') #每一筆資料在管理介面顯示的內容以下列程式定義 def __str__(self): return self.cName #表示顯示cName欄位
(2)model.Model 常用的欄位、欄位的屬性
前面範例已經有介紹幾個,還有許多的欄位請至官網深入了解 點此連結
(3)建立 migration 資料檔
資料庫模型建立完成後,必須將建立資料表的架構和版本記錄下來,以利以後的追蹤。
如果專案伺服器是啟動中的,請按 CTRL+C 關閉伺服器,回到students 目錄,並以「python manage.py makemigrations」更新migrations目錄。
接著以「 python manage.py migrate」進行migrate,migrate會根據migrations紀錄將模型同步到資料庫。
二、admin 後台管理與 ModelAdmin 類別:
Migrate 成功後會在專案跟目錄下建立 <db.sqlite3> 資料庫,利用 admin 可以管理後台,新增、修改或刪除。
1. admin 後台管理
請開啟 studentsapp 目錄底下的 <admin.py> 並寫入以下程序:
from django.contrib import admin #因為student定義在models.py,所以需要import來加入該套件 from studentsapp.models import student #下面會以register的方式,將建立的資料模型向admin註冊 admin.site.register(student)
記得要儲存文件,接下來先關閉server,要建立管理者帳號密碼來登入admin
這邊帳號先以admin,信箱設為admin@admin.com,密碼設為aa000000(不能設為全數字)
創建完後就可以再次啟動伺服器,輸入「127.0.0.1:8000/admin」就會開啟admin登入畫面
登入之後就會看到之前註冊的資料表students
點選資料表後面的新增,即可進入資料輸入的頁面
1新增後資料會以cName欄位顯示,因為之前在<Model.py>中做過設定(忘記的話可以往回看)
點選右上的新增可以繼續新增多筆資料,這邊又新增了兩筆資料,最後顯示如下:
2.定義 ModelAdmin 類別
在 Admin 中可以設定顯示多個類別,也可以依據指定欄位過濾資料或搜尋與排序
(1)顯示多個欄位
要在 Admin 中顯示多個欄位 要在 <admin.py> 中定義 ModelAdmin 類別,再以list_display 定義顯示的欄位,最後透過 register 的方式註冊
這邊有三種方式來顯示欄位:
第一種方式,直接 register 註冊資料表,沒有加入 ModelAdmin 類別
第二種方式,加入ModelAdmin 類別,定義顯示欄位
第三種方式,加入ModelAdmin 類別,定義顯示欄位、欄位過濾資料、搜尋和排序
依據想要採用的方式,拿掉或加上註解,這邊是採用第三種方式來顯示
from django.contrib import admin #因為student定義在models.py,所以需要import來加入該套件 from studentsapp.models import student #第一種方式:直接以register的方式,將建立的資料模型向admin註冊 # admin.site.register(student) #第二種方式:加入ModelAdmin 類別,定義顯示欄位 # class studentAdmin(admin.ModelAdmin): # list_display=('id','cName','cSex','cBirthday','cEmail','cPhone','cPhone','cAddr') # admin.site.register(student,studentAdmin) #第三種方式:加入ModelAdmin 類別,定義顯示欄位、欄位過濾資料、搜尋和排序 class studentAdmin(admin.ModelAdmin): list_display=('id','cName','cSex','cBirthday','cEmail','cPhone','cAddr') list_filter=('cName','cSex') search_fields=('cName',) ordering=('id',) admin.site.register(student,studentAdmin)
這邊講解一下第三種方法的程式碼:
- 資料過濾:list_filter可以建立過濾的欄位。必須使用串列或元組,會在右方顯示。
- 依據欄位搜尋:search_fields 可以依據指定的欄位搜尋,必須使用串列或元組,會在上方出現文字方塊以供搜尋(依據指定的欄位)。
- 排序:ordering 可以依據指定的欄位排序,必須使用串列或元組,加上「-」可以遞減排序。例如 ordering=('-id')。
以下是顯示出來的結果:
三、資料庫查詢:
利用 models 模組的 objects.get() 和 objects.all() 方法可以讀取資料
1. get() 方法
get()方法可以取得一筆資料,語法:
資料表.objects.get(查詢條件)
objects.get() 查詢成功會傳回1筆資料,若回傳是多筆資料或是資料不存在,都會產生錯誤,因此通常會做例外處理。
範例1. 以Template樣版顯示資料
首先請打開studentsapp裡的<view.py>寫一個名為listone的自訂函數
會先做try/except 的例外處理,如果try成功的話,則讀取cName欄位的'ivan'那列的所有資料,且將資料儲存在unit變數
from django.shortcuts import render from studentsapp.models import student def listone(request): try: unit = student.objects.get(cName="ivan") #讀取第一筆資料 except: errormessage = "(讀取錯誤!)" return render(request,'listone.html',locals())
接著在templates目錄中創建一個<listone.html>模版
- 若try失敗就會顯示except的內容 {{errormessage}}
- {{unit.id}}顯示自動編號的 id 欄位,其餘的也是如此
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>顯示第一筆資料</title> </head> <body> <h2>顯示 student資料表一筆資料 {{errormessage}}</h2> 編號: {{unit.id}} <br /> 姓名: {{unit.cName}} <br /> 性別: {{unit.cSex}} <br /> 生日: {{unit.cBirthday}} <br /> 郵件帳號: {{unit.cEmail}} <br /> 電話: {{unit.cPhone}} <br /> 地址: {{unit.cAddr}} <br /> </body> </html>
最後記得在<urls.py>新增listone的url路徑(或是去掉之前的註解)
最後網頁執行結果如下:
2. objects.all() 方法
objects.all() 方法可以讀取資料表中的每一筆資料,語法:
資料表.objects.all
也可以將資料以「.order_by("欄位")」依據指定的欄位做排序,預設為遞增,加上「-」則是遞減排序。
範例2. 以Template樣版顯示全部資料
請打開studentsapp裡的<view.py>寫一個名為listall的自訂函數
讀取id欄位的的所有資料,並且使用「-」的方式來遞減排序,最後將資料儲存在students變數
def listall(request): students = student.objects.all().order_by('-id') #依據id欄位遞減排序顯示所有資料 return render(request,'listall.html',locals())
接著在templates目錄中創建一個<listall.html>模版
- 使用for迴圈將students裡面的student串列資料一一取得
- {{student.id}}顯示自動編號的 id 欄位,其餘的也是如此
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>顯示所有資料</title> </head> <body> <h2>顯示 student資料表所有資料</h2> {% for student in students %} 編號: {{student.id}} <br /> 姓名: {{student.cName}} <br /> 性別: {{student.cSex}} <br /> 生日: {{student.cBirthday}} <br /> 郵件帳號: {{student.cEmail}} <br /> 電話: {{student.cPhone}} <br /> 地址: {{student.cAddr}} <br /> <br /> {% endfor %} </body> </html>
最後記得在<urls.py>新增listall的url路徑(或是去掉之前的註解)
網頁執行結果如下:
這樣子看資料很不方便,所以最後我們在<listall.html>幫我們的資料加上table語法,讓資料整齊地以表格的方式顯示
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>顯示所有資料</title> </head> <body> <h2>顯示 student資料表所有資料</h2> <table border="1" cellpadding="0" cellspacing="0"> <th>編號</th> <th>姓名</th> <th>性別</th> <th>生日</th> <th>郵件帳號</th> <th>電話</th> <th>地址</th> {% for student in students %} <tr> <td>{{student.id}} </td> <td>{{student.cName}} </td> <td>{{student.cSex}} </td> <td>{{student.cBirthday}} </td> <td>{{student.cEmail}} </td> <td>{{student.cPhone}} </td> <td>{{student.cAddr}} </td> </tr> {% endfor %} </table> </body> </html>
最後網頁執行結果如下:
四、網頁基礎模版:
網站個網頁通常會採用相同風格,例如同樣的頁首頁尾,所以會將相同的部分抽離出來,另外建立模版。
1. 建立網頁基礎模版
在基礎模版中,首先將共同的部份抽離出來,也可以以「{% block 名稱 %}{% endblock %}」來定義區塊
呼叫模版必須以「{% extends 基礎模版 %}」來繼承基礎模版,並設定block區塊內容
以下將以<listall.html>樣版為例,將其拆解為<base.html>與<index.html>
範例3. 建立網頁模版與繼承模版
首先先在studentsapp裡的<view.py>寫一個名為index的自訂函數,其內容同listall,但指向的網址要改為"index.html"
接著在templates目錄中創建一個<base.html>模版
- 以block定義title區塊
- 在body中定義content區塊
<!DOCTYPE html> <html> <head> <!-- 以block定義title區塊 --> {% block title %}{% endblock %} </head> <body> <!-- 以block定義content區塊 --> {% block content %} {% endblock %} </body> </html>
最後在templates目錄中創建一個<index.html>模版
- 繼承 <base.html>基礎模版
- 建立title區建立content區塊
- 設定網頁主題
- 建立表格顯示所有資料
在body中定義content區塊
{% extends 'base.html' %} {% block title %} <meta charset="utf-8"> <title>顯示所有資料</title> {% endblock %} {% block content %} <h2>顯示 student資料表所有資料</h2> <table border="1" cellpadding="0" cellspacing="0"> <th>編號</th> <th>姓名</th> <th>性別</th> <th>生日</th> <th>郵件帳號</th> <th>電話</th> <th>地址</th> {% for student in students %} <tr> <td>{{student.id}} </td> <td>{{student.cName}} </td> <td>{{student.cSex}} </td> <td>{{student.cBirthday}} </td> <td>{{student.cEmail}} </td> <td>{{student.cPhone}} </td> <td>{{student.cAddr}} </td> </tr> {% endfor %} </table> {% endblock %}
最後網頁執行結果如下:
留言列表