談談Python之Django搭建企業級官網(第四篇上)

轉載請註明來源地址和原作者(CFishHome)

前沿

本篇文章將介紹模板相關的內容,例如:DTL模板語法(變量、模板標籤、過濾器、自定義過濾器)。只要一步一步跟着一起操作,我相信模板這一塊的內容毫無難度,就好像學習MarkDown一樣好學好用。在此,因爲前不久學校有很多事要處理,所以學習筆記耽擱了幾天,趁國慶好好補補落下的內容,還有本篇DTL語法涉及衆多,所以決定分上中下篇來講解和總結。

學前工作

我們先創建一個名爲my_template的新Django項目。因爲這篇內容涉及的是模板內容,跟app關係不大,所以在這裏我就不創建一個app來進行URL映射了,而是直接在my_template主包
裏添加一個views.py文件進行URL映射。整體框架如下圖所示:
談談Python之Django搭建企業級官網(第四篇上)
(1)爲views.py添加以下代碼:

from django.http import HttpResponse

def index(request):
    return HttpResponse("首頁")

(2)修改urls.py代碼如下:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name="index")
]

運行項目,能成功訪問127.0.0.1:8000,好了學前工作準備完畢,下面正式進入模板的學習。

模板

在前面的學習中,我們編寫的視圖函數只是直接返回文本,例如:HttpResponse("首頁"),而在實際生產環境中其實很少這樣用,因爲實際的頁面大多是帶有樣式的HTML代碼,這可以讓瀏覽器渲染出非常漂亮的頁面。目前市面上有非常多的模板系統,其中最知名最好用的就是DTL和Jinja2。 DTL 是 Django Template Language 三個單詞的縮寫,也就是Django自帶的模板語言。當然也可以配置Django支持Jinja2等其他模板引擎,但是作爲Django內置的模板語言,和Django可以達到無縫銜接而不會產生一些不兼容的情況。因此建議大家學習好DTL。
現在總結下概念,爲後面的學習做準備:

DTL(Django Template Language )名叫Django模板語言,用DTL編寫的是一個DTL模板文件,這個文件是一個帶有特殊語法的HTML文件,利用pycharm創建一個Django項目,那麼會自動生成一個template文件夾,這個文件夾就是存放項目的DTL模板文件(也就是帶有特殊語法的HTML文件)。在視圖函數裏面可以利用render_to_string方法將指定的DTL模板文件編譯後渲染成Python的字符串格式,然後用HttpResponse方法打包返回給客戶端,或者在視圖函數裏面直接利用render方法將指定的DTL模板文件渲染接着自動打包成HttpResponse,然後視圖函數返回給客戶端。

渲染模板

渲染模板有多種方式。這裏講下兩種常用的方式。
(1) render_to_string:該函數會自動在templates文件夾搜尋DTL模板文件,找到後接着將DTL模板文件編譯後渲染成Python的字符串格式。最後再通過HttpResponse類包裝成一個HttpResponse 對象返回回去。
1.修改views.py代碼如下:

from django.template.loader import render_to_string
from django.http import HttpResponse

def index(request):
    html = render_to_string("index.html")  # 該函數在templates文件夾搜尋是否含有index.html文件,找到後將該文件(DTL模板文件)編譯後渲染成Python的字符串格式
    return HttpResponse(html)  # 然後將html通過HttpResponse包裝後返回給瀏覽器進行顯示

2.templates文件夾就是專門存放DTL模板文件的,在工程目錄中可以找到這個文件夾。然後在templates文件夾下添加index.html文件,如下圖所示:
談談Python之Django搭建企業級官網(第四篇上)
3.添加index.html後,默認會生成一些html5的代碼,接着我們修改該文件,在瀏覽器中顯示一段文字:
談談Python之Django搭建企業級官網(第四篇上)
4.運行Django項目,然後輸入127.0.0.1:8000,顯示結果如下(成功訪問到了我們渲染的模板文件index.html):
談談Python之Django搭建企業級官網(第四篇上)
(2)以上方式雖然已經很方便了。但是django還提供了一個更加簡便的方式-render方法(推薦該方式),直接將模板渲染成字符串和包裝成 HttpResponse 對象一步到位完成。
1.在前一個測試render_to_string方法的代碼基礎上,修改views.py文件代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, "index.html")  # render方法很方便,只要第一個參數指定request對象,第二個參數指定模板文件的路徑,然後它會自動在templates文件夾下搜尋該文件,然後自動渲染再用HttpResponse包裝返回。

按下Ctrl+S保存,輸入127.0.0.1:8000,顯示結果如下(再次成功訪問到了我們渲染的模板文件index.html):
談談Python之Django搭建企業級官網(第四篇上)
2.分析render函數的內部實現,源代碼如下圖:
談談Python之Django搭建企業級官網(第四篇上)
從上圖可以看出,其實render方法內部也是調用render_to_string渲染、HttpResponse包裝再返回,直接使用render方法減輕了我們對代碼的編寫,並且讓代碼更美觀簡潔,嗯~的確不錯。

模板查找路徑配置

上一小節我介紹瞭如何渲染模板,其中render或render_to_string方法有一個參數是指定DTL模板文件,然後在templates文件夾下查找指定的DTL模板文件。其實,對於DTL模板文件有一個專門的查找路徑,容許我一一道來。在項目的 settings.py 文件中。有一個 TEMPLATES 配置,這個配置包含了模板引擎的配置,模板查找路徑的配置等。如下圖所示:
談談Python之Django搭建企業級官網(第四篇上)
這個TEMPLATES配置裏面有兩個重要的屬性:DIRS、APP_DIRS。DTL模板文件查找路徑可以通過這兩個屬性配置。
(1) DIRS :這是一個列表,在這個列表中可以存放所有的DTL模板文件路徑,以後在視圖中使用 render 或者 render_to_string 渲染模板的時候,會在這個列表的路徑中查找模板。一般情況下是“os.path.join(BASE_DIR, 'templates')”,os.path.join()函數是將BASE_DIR和‘templates’拼接,其中BASE_DIR是當前項目的路徑,注意,不論項目被移動到哪個目錄下,BASE_DIR都會動態修改當前項目的路徑,怎麼實現動態?一樣定位到settings.py文件前面的代碼,如下圖:
談談Python之Django搭建企業級官網(第四篇上)
意思是說無論將項目放到哪裏,利用render等函數渲染模板時,都可以找到templates目錄下的DTL模板文件,因爲BASE_DIR和‘templates’拼接起來其實就是templates文件夾的絕對路徑。
(2)APP_DIRS :默認爲 True ,這個設置爲 True 後,如果在DIRS指定的模板查找路徑不能找到模板文件,那麼就會在 INSTALLED_APPS 安裝了的APP下的 templates 文件加中查找模板。一樣定位到settings.py文件前面的代碼,如下圖(默認安裝了一些Django項目必須的app):
談談Python之Django搭建企業級官網(第四篇上)
這個APP_DIRS的作用是當DIRS不能找到模板文件時,就在其他app上查找模板,需要進行以下兩步:1.在INSTALLED_APPS添加app的名字。例如:"front"。2.在app目錄下創建一個名爲templates的文件夾(必須是這個名字,其他不允許),然後添加DTL模板文件。那麼當DIRS找不到時就跑這個app裏的templates目錄找模板。

模板查找路徑小總結

DTL模板文件查找順序:比如代碼 render('list.html') 。先會在 DIRS 這個列表中依次查找路徑下有沒有這個模板,如果有,就返回。如果 DIRS 列表中所有的路徑都沒有找到,那麼會先檢查當前這個視圖所處的 app (什麼叫當前這個視圖所在的app?其實就是假如views.py在front這個app目錄下,那麼front就是當前這個視圖所處的app。) 是否已經安裝,如果已經安裝了,那麼就先在當前這個 app 下的 templates 文件夾中查找模板,如果沒有找到,那麼會在其他已經安裝了的 app 中查找。如果所有路徑下都沒有找到,那麼會拋出一個 TemplateDoesNotExist 的異常。

DTL模板語法

變量

模板中可以包含變量, Django 在渲染模板的時候,可以傳遞變量對應的值過去進行替換。變量的命名規範和 Python 非常類似,只能是阿拉伯數字和英文字符以及下劃線的組合,不能出現標點符號等特殊字符。變量需要通過視圖函數渲染,視圖函數在使用 render 或者 render_to_string 的時候可以傳遞一個 context 的參數,這個參數是一個字典類型。以後在模板中的變量利用{{變量名}}從這個字典中讀取值的。
舉個變量的栗子:
(1)修改views.py代碼如下(添加context參數來爲DTL模板文件傳遞變量):

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "username": "CFishHome學習"
    }
    return render(request, "index.html", context=context)  # 函數指定關鍵字參數context來傳遞變量

(2)修改index.html模板的代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
    {{ username }}  
</body>
</html>

按下Ctrl+S保存,注意要在python文件保存,在index.html下保存不能自動重新運行。運行結果如下:
談談Python之Django搭建企業級官網(第四篇上)

各種變量類型的解析

事實上,context字典鍵一般爲變量名(字符串類型),而值有多種類型,其中包括前面列舉的字符串、字典、元組、列表、類對象、函數名等。下面一一舉例測試常用的幾種變量類型的使用,字符串類型前面已列舉,這裏不再演示:
(1)字典
與Python語法不同的是,DTL語法不允許通過中括號的形式訪問字典或列表中的值,比如dict['key']和list[1]是不支持的!不要問爲什麼,規則是那些大牛們定下來的,我們只能遵循他們定下的規則。
修改views.py代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": {
            "book_id": "A001",
            "book_name":"人民的名義",
            "book_price":1000
        }
    }
    return render(request, "index.html", context=context)

修改index.html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.book_id }}</p>
<p>{{ book.book_name }}</p>
<p>{{ book.book_price }}</p>
</body>
</html>

按下Ctrl+S保存,運行結果如下(成功訪問字典的鍵所對應的值):
談談Python之Django搭建企業級官網(第四篇上)
因爲字典可以使用點(.)語法獲取字典鍵所對應的值,並且也可以使用點(.)語法調用字典內置的方法,所以在給這個字典添加key的時候,千萬不能和字典中的一些屬性或方法重複。比如items,items是字典的方法,那麼如果給這個字典添加一個items作爲key,那麼以後就不能再通過item來訪問這個字典的鍵值對了,而是變成訪問我們自定義的items鍵所對應的自定義的值了。下面舉個栗子:
1.通過{{ 變量名.函數名 }}就可以調用該變量對應的函數了,修改index.html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.book_id }}</p>
<p>{{ book.book_name }}</p>
<p>{{ book.book_price }}</p>
<p>{{ book.keys }}</p>
</body>
</html>

運行結果如下,通過字典內置的keys方法,成功訪問到了該字典含有的所有鍵:
談談Python之Django搭建企業級官網(第四篇上)
2.修改views.py文件的context內容,添加與字典內置函數Keys衝突的keys鍵和對應的值,代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": {
            "book_id": "A001",
            "book_name": "人民的名義",
            "book_price": 1000,
            "keys": 200
        }
    }
    return render(request, "index.html", context=context)

按下Ctrl+S保存,運行結果如下:
談談Python之Django搭建企業級官網(第四篇上)
從上圖可以看出,我們自定義的與字典內置函數keys衝突的keys鍵被解析顯示在頁面上,但是字典內置函數keys永遠都執行不到了,因爲被覆蓋了。所以在此提個建議:給字典添加key的時候,千萬不能和字典中的一些屬性或方法重複,不然會被覆蓋。
(2)列表或者元組
如果book是一個列表或者元組,是不能通過中括號的形式訪問列表和元組中的值,比如list[1]是不支持的!只能夠通過'.'來訪問。
1.修改views.py文件的context內容,代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": ["水滸傳", "人民的名義", "魯迅自傳", "鋼鐵是怎樣煉成的"],
        "price": (100, 200, 300, 400)
    }
    return render(request, "index.html", context=context)

2.通過{{ 變量名.下表 }}就可以訪問該變量對應的元素值了,修改index.html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.0 }}</p>
<p>{{ book.1 }}</p>
<p>{{ book.2 }}</p>
<p>{{ book.3 }}</p>
<p>{{ price.0 }}</p>
<p>{{ price.1 }}</p>
<p>{{ price.2 }}</p>
<p>{{ price.3 }}</p>
</body>
</html>

按下Ctrl+S保存,運行結果如下:
談談Python之Django搭建企業級官網(第四篇上)
(3)類對象
如果book是一個對象,那麼就會可以在模板訪問這個對象的屬性,或者是方法。
1.修改views.py文件的context內容,代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

class A:
    def __init__(self, count):
        self.count=count

    def show(self):
        print("我是一個類")

def index(request):
    a = A(100)
    context = {
        "book": a
    }
    return render(request, "index.html", context=context)

2.通過{{ 變量名.屬性或者函數名 }}就可以訪問該對象對應的屬性或調用對應的函數了,修改index.html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.show }}</p>
<p>{{ book.count }}</p>
</body>
</html>

按下Ctrl+S保存,運行結果如下:
談談Python之Django搭建企業級官網(第四篇上)
由上可得出,在DTL模板文件成功訪問到對象的屬性,第一個輸出的是None,因爲只是單純的調用(輸出信息在下圖所示控制檯)。
談談Python之Django搭建企業級官網(第四篇上)
(4)函數
book也可以是一個函數名(例如:show或show()),代表這個函數,在DTL模板文件中引用時也是{{ 變量名 }}方式調用函數,需要注意的是這種方式是無法傳遞函數參數的,所以這個函數在定義時寫參數也沒用。
1.修改views.py文件的context內容,代碼如下:

from django.shortcuts import render
from django.http import HttpResponse

def show():
    print("我是一個簡單的函數")

def index(request):
    context = {
        "book": show
    }
    return render(request, "index.html", context=context)

2.通過{{ 變量名.函數名 }}就可以訪問該函數了,修改index.html代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.show }}</p>
</body>
</html>

按下Ctrl+S保存,運行結果如下:
談談Python之Django搭建企業級官網(第四篇上)

Django測試項目8000端口被酷狗佔用問題

創建了一個Django項目,但是運行時報錯可能會報下面這個錯誤:
談談Python之Django搭建企業級官網(第四篇上)
爲什麼會報這個錯誤?其實就是端口被佔用了,那以我目前這個電腦程序運行情況舉例,我開機->打開酷狗(聽音樂)->打開pycharm->創建Django項目(默認使用8000端口)->運行項目->報端口占用錯誤。
我們打開CMD執行以下命令:
談談Python之Django搭建企業級官網(第四篇上)
第一條命令找出8000端口對應的PID進程爲2032,第二條命令通過進程ID找出進程對應的詳細信息,可以看到這個進程對應的是酷狗服務。問題找到了,就是因爲我們先開啓了酷狗,酷狗服務佔用了我們的測試端口。所以解決辦法有兩個:

1.關閉酷狗再重新運行Django項目。

2.將Django項目的測試端口改爲其他,例如:9000

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章