使用模板渲染页面
- 在 bicycle 目录下创建 templates 子目录,并在其中创建两个模板文件:base.html 和 bicycle.html 。
<!--base.html-->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!--bicycle.html-->
{% extends "base.html" %}
{% block title %}My {{ color }} bicycle{% endblock %}
{% block content %}
<h2>This is my <span style="color:{{ color }}">{{ color }}</span> bicycle.</h2>
<pre style="color:{{ color }}; font-family:Courier New">
$" *.
d$$$$$$$P" $ J
^$. 4r "
d"b .db
P $ e" $
..ec.. ." *. zP $.zec..
.^ 3*b. *. .P" .@"4F "4
." d" ^b. *c .$" d" $ %
/ P $. "c d" @ 3r 3
4 .eE........$r===e$$$$eeP J *.. b
$ $$$$$ $ 4$$$$$$$ F d$$$. 4
$ $$$$$ $ 4$$$$$$$ L *$$$" 4
4 " ""3P ===$$$$$$" 3 P
* $ """ b J
". .P %. @
%. z*" ^%. .r"
"*==*"" ^"*==*""
</pre>
{% endblock %}
- 修改 bicycle/views.py ,改为返回
TemplateResponse
对象。
from django.template.response import TemplateResponse
def my_bicycle(request):
context = {'color': 'blue'}
return TemplateResponse(request, 'bicycle.html', context)
也可以使用 render()
,效果一样。
from django.shortcuts import render
def my_bicycle(request):
context = {'color': 'blue'}
return render(request, 'bicycle.html', context)
- 运行后,访问 http://127.0.0.1:8000/bicycle/ 效果如下:
- 可以在项目的 settings.py 中对模板系统进行定制,比如修改
DIRS
,不过一般没有必要。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
接收请求参数
通过 QueryString 传参
修改 bicycle/views.py,从 request.GET
获得 color
参数:
from django.template.response import TemplateResponse
def my_bicycle(request):
context = {'color': request.GET['color']}
return TemplateResponse(request, 'bicycle.html', context)
在浏览器中请求 http://127.0.0.1:8000/bicycle/?color=brown ,得到以下页面:
即使是使用 POST
方法请求上面的 URL,也是一样的结果(尝试前先禁用 django 的 csrf 中间件,关闭 csrf 保护机制):
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',
]
C:\>curl -X POST http://127.0.0.1:8000/bicycle/?color=brown
<!DOCTYPE html>
<html>
<head>
<title>My brown bicycle</title>
</head>
<body>
<h2>This is my <span style="color:brown">brown</span> bicycle.</h2>
<pre style="color:brown; font-family:Courier New">
$" *.
d$$$$$$$P" $ J
^$. 4r "
d"b .db
P $ e" $
..ec.. ." *. zP $.zec..
.^ 3*b. *. .P" .@"4F "4
." d" ^b. *c .$" d" $ %
/ P $. "c d" @ 3r 3
4 .eE........$r===e$$$$eeP J *.. b
$ $$$$$ $ 4$$$$$$$ F d$$$. 4
$ $$$$$ $ 4$$$$$$$ L *$$$" 4
4 " ""3P ===$$$$$$" 3 P
* $ """ b J
". .P %. @
%. z*" ^%. .r"
"*==*"" ^"*==*""
</pre>
</body>
</html>
通过 Body 传参
刚才是通过直接禁用 csrf 中间件来关闭 django 的 csrf 保护机制,但一般不要这么做,最好是用 @csrf_exempt
装饰器来免除对某个视图的保护。这次通过 request.POST
获得传入的参数,将 bicycle/views.py 修改为:
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_bicycle(request):
context = {'color': request.POST['color']}
return TemplateResponse(request, 'bicycle.html', context)
使用 curl 执行 POST
请求:
C:\>curl -X POST http://127.0.0.1:8000/bicycle/ -d "color=green"
<!DOCTYPE html>
<html>
<head>
<title>My green bicycle</title>
</head>
<body>
<h2>This is my <span style="color:green">green</span> bicycle.</h2>
<pre style="color:green; font-family:Courier New">
$" *.
d$$$$$$$P" $ J
^$. 4r "
d"b .db
P $ e" $
..ec.. ." *. zP $.zec..
.^ 3*b. *. .P" .@"4F "4
." d" ^b. *c .$" d" $ %
/ P $. "c d" @ 3r 3
4 .eE........$r===e$$$$eeP J *.. b
$ $$$$$ $ 4$$$$$$$ F d$$$. 4
$ $$$$$ $ 4$$$$$$$ L *$$$" 4
4 " ""3P ===$$$$$$" 3 P
* $ """ b J
". .P %. @
%. z*" ^%. .r"
"*==*"" ^"*==*""
</pre>
</body>
</html>
但当使用 PUT
、DELETE
、GET
等方法时,request.POST
中就不再包含 body 参数了,更通用的方法是将 request.body
转换为 QueryDict
:
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
from django.http import QueryDict
@csrf_exempt
def my_bicycle(request):
data = QueryDict(request.body)
context = {'color': data['color']}
return TemplateResponse(request, 'bicycle.html', context)
C:\>curl -X PUT http://127.0.0.1:8000/bicycle/ -d "color=red"
<!DOCTYPE html>
<html>
<head>
<title>My red bicycle</title>
</head>
<body>
<h2>This is my <span style="color:red">red</span> bicycle.</h2>
<pre style="color:red; font-family:Courier New">
$" *.
d$$$$$$$P" $ J
^$. 4r "
d"b .db
P $ e" $
..ec.. ." *. zP $.zec..
.^ 3*b. *. .P" .@"4F "4
." d" ^b. *c .$" d" $ %
/ P $. "c d" @ 3r 3
4 .eE........$r===e$$$$eeP J *.. b
$ $$$$$ $ 4$$$$$$$ F d$$$. 4
$ $$$$$ $ 4$$$$$$$ L *$$$" 4
4 " ""3P ===$$$$$$" 3 P
* $ """ b J
". .P %. @
%. z*" ^%. .r"
"*==*"" ^"*==*""
</pre>
</body>
</html>
通过 URL 传参
采用 RESTful 风格的设计时,更优雅的传参方式是通过 URL 传参,为此需修改 bicycle/urls.py :
from django.urls import path
from .views import my_bicycle
urlpatterns = [
path('<str:color>/', my_bicycle),
]
或者使用正则表达式 re_path
:
from django.urls import re_path
from .views import my_bicycle
urlpatterns = [
re_path('(?P<color>[a-z]+)/', my_bicycle),
]
然后修改 bicycle/views.py :
from django.template.response import TemplateResponse
def my_bicycle(request, color):
context = {'color': color}
return TemplateResponse(request, 'bicycle.html', context)
打开浏览器,访问 http://127.0.0.1:8000/bicycle/pink/ :
响应 JSON 数据(而非 HTML 页面)
通过自行车 ID 得到自行车的颜色,使用 JsonResponse
可返回 JSON 格式的数据。修改 bicycle/urls.py 和 bicycle/views.py :
from django.urls import path
from .views import my_bicycle
urlpatterns = [
path('<int:id>/', my_bicycle),
]
from django.http import JsonResponse
def my_bicycle(request, id):
color = {
1: 'yellow',
2: 'red',
3: 'blue'
}
data = {
'id': id,
'color': color[id]
}
return JsonResponse(data)
使用 curl 发起请求:
C:\>curl -X GET http://127.0.0.1:8000/bicycle/1/
{"id": 1, "color": "yellow"}
Http404
当在程序中抛出 Http404
异常时,Django 会加载一个专门处理 404 错误的视图。默认情况下是视图 django.views.defaults.page_not_found() 。
from django.http import JsonResponse, Http404
def my_bicycle(request, id):
color = {
1: 'yellow',
2: 'red',
3: 'blue'
}
if id < 1 or id > 3:
raise Http404
else:
data = {
'id': id,
'color': color[id]
}
return JsonResponse(data)
基于类的视图
基于类的视图提供另一种将视图实现为 Python 对象而不是函数的方法。它们不能替代基于函数的视图,但与基于函数的视图相比,它们是有某些不同和优势的。
- Organization of code related to specific HTTP methods (GET, POST, etc.) can be addressed by separate methods instead of conditional branching.
- Object oriented techniques such as mixins (multiple inheritance) can be used to factor code into reusable components.
例如,对于 GET
请求,返回 HTML页面;对于 POST
请求,返回 JSON 数据。如果使用基于类的视图,则将 bicycle/views.py 修改为:
from django.template.response import TemplateResponse
from django.http import JsonResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt, name='dispatch')
class MyBicycle(View):
color = {
1: 'yellow',
2: 'red',
3: 'blue'
}
def get(self, request, id):
context = {'color': self.color[id]}
return TemplateResponse(request, 'bicycle.html', context)
def post(self, request, id):
context = {
'id': id,
'color': self.color[id]
}
return JsonResponse(context)
同时,需要修改 bicycle/urls.py :
from django.urls import path
from .views import MyBicycle
urlpatterns = [
path('<int:id>/', MyBicycle.as_view()),
]
以上是视图的基本用法,更多详细内容则请查阅文档。