Python Django 概念與實作 - Django View(一)
前言
Django採用MVT(model, view, tempalte)架構,這節來大概說一下其大致的流程、MVT與MVC差異,最後介紹view中常用的函數與方法~
目前 Python Django 概念與實作 大致規劃為
- 佈置環境
- Django View(一)
- Django Model(二)
- Django Test(三)
- Django Forms(四)
- Django Admin(五)
- 登入功能(六)
- Blog功能(七)
MVT

MVT(model, view, tempalte)框架與MVC(model, view, controller)其實根本一樣(?)。在MVT中,View負責處理邏輯、返回response(接收request由url負責),Template負責頁面渲染,Model負責與DB server存取data。
在MVC中,Controller負責接收request、返回response、與view溝通,View負責處理邏輯、頁面渲染,Model一樣負責存取data。
Create Application
介紹完django中的MVT框架後,我們建立一個view看看。
除了基本設定外,django可以新增各種子功能,這裡我們新增一個posts功能
python manage.py startapp posts
django會自動幫我們新增一個post資料夾,與主設定App(main)同一層
1 | . |
- 在
posts/apps找到app設定檔名PostsConfig後,註冊app1
2
3
4
5# posts/apps.py
from django.apps import AppConfig
class PostsConfig(AppConfig): # app設定檔名
default_auto_field = 'django.db.models.BigAutoField'
name = 'posts'1
2
3
4
5
6
7
8
9
10
11
12
13# main/setting.py
# 略
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts.apps.PostsConfig', # 註冊app
] - 修改
views.py1
2
3
4
5
6# posts/views.py
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse('Blog - 首頁')Tips
在views.py中,傳至前端必須是一個HttpResponse物件,無法像Flask一樣直接返回字串 - 新增
urls.py,注意⚠️這裡的URL是接在main_app URL後方。e.g. localhost:8000/blog/index1
2
3
4
5
6
7
8# posts/urls.py
from django.urls import path
from posts import views
app_name = 'posts'
urlpatterns = [
path("", views.index, name="index"),
] - 修改
main/urls.py,註冊app URL,這裡才是第一層的URL。e.g. localhost:8000/blog1
2
3
4
5
6
7
8# main/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog', include('posts.urls')),
]
儲存後,在/blog就可以看到我們的第一個網頁🎉
Template
在viws.py中,直接注入html是不切實際的,django也支援使用template(模板)
- 在
post中新增templates/post資料夾Notices
雖然可以直接將.html丟入templates資料夾中,但django仍然建議我們多一層app_name資料夾,避免django搞混 - 新增
base.html,這裡我新增了一個bootstrap的navbar1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54<!-- posts/templates/posts/base.html -->
<html lang="zh-CN">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<title>My blog</title>
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">My Blog</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main>
{% block container %}
{% endblock %}
</main>
<!-- JS files -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
</body>
</html> - 新增
index.html,並繼承base.html1
2
3
4<!-- posts/templates/posts/index.html -->
{% extends 'posts/base.html' %}
{% block container %}
{% endblock %} - 修改
posts/views.py存檔後可以看到bootstrap樣式1
2
3
4
5
6
7# posts/views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
def index(request):
template = loader.get_template('posts/index.html')
return HttpResponse(template.render(request=request))
Context
Context(上下文),僅將模板輸出至前端是不夠的,django使用dict方法提供我們將變數輸出至前段
- 修改
posts/views.py1
2
3
4
5
6
7
8# posts/views.py`
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
def index(request):
template = loader.get_template('posts/index.html')
context = {'username': 'MC'}
return HttpResponse(template.render(context=context, request=request)) - 修改
posts/templates/posts/index.html1
2
3
4
5<!-- posts/templates/posts/index.html -->
{% extends 'posts/base.html' %}
{% block container %}
<h1>Welcome, {{ username }}</h1>
{% endblock %}
Render
每一次都要使用HttpResponse與loader有點麻煩,django預設是使用更為簡潔的render
- 修改
posts/views.py1
2
3
4
5# posts/views.py
from django.shortcuts import render
def index(request):
context = {'username': 'MC'}
return render(request, 'posts/index.html', context=context)Tips
雖然render()更為簡潔,但本質仍是HttpResponse物件
Static Files
django中的static file(.css, .js, .img)放置方式與template相同
- 修改
setting.py❗️重要❗️1
2
3
4# main/setting.py
# 略...
# STATIC_URL = 'static/'
STATIC_URL = '/static/' # 多加'/' - 在
posts中新增/static/posts - 在
/ststic/posts下新增/img/django.png,可自行抓取圖片1
2
3
4
5
6posts
└── static
└── posts
└── img
└── django.png - 在
.html引入static就可以使用static1
2
3
4
5
6
7<!-- posts/index.html -->
{% extend base.html %}
{% load static %}
{% block container %}
<h1>Welcome, {{ username }}</h1>
<img src="{% static 'posts/img/django-icon.png' %}" style="height: 200px;">
{% endblock %}Notices
即使base.html中已經有{% load static %}標籤,子模板中仍需要使用該標籤,否則會顯示TemplateSyntaxError
結論
- MVT, MVC框架
- 新增app
- 修改URL
-
HttpResponse返回至前端 -
loader()渲染html -
context(上下文) -
render()快速渲染 - 使用template, static