(一)准备工作
本小节大概要花费20分钟。
让我们在进入正题之前,先做一些准备工作。读者可以自行跳过自己熟悉的部分。
本小节主要内容有:
- 安装Django
- 新建Django项目
- 对一个简单的HttpRequest做出响应
- 解析带参数的URL
- 处理HTTP请求的body
1. 安装Django
$ pip3 install Django==2.0.5
pip3是python3中用来进行包管理的工具。
如果提示没有权限,则需要在pip3前sudo。另一种不需要sudo的方法是使用virtualenv。
安装成功后,我们就可以运行django-admin命令来创建项目了。
2. 新建项目
$ django-admin startproject task_platform
这里,我们新建了一个叫做task_platform的项目,其目录结构如图:
新建的Django项目目录结构
其中:
- manage.py用来运行Django项目的一些特殊功能
- 和项目名同名的文件夹task_platform中存放了项目根url路由(url.py)以及项目配置信息(settings.py)
- wsgi.py我们暂时不考虑
这个时候,我们的项目已经可以运行了:
$ python3 manage.py runserver
... ...
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
这条命令会让Django启动一个临时的服务器。如上,你会收到提示说,服务器已经在 http://127.0.0.1:8000/ 开启了。用浏览器访问 http://127.0.0.1:8000/,就可以看到Django提供的初始界面了:
Django提供的初始页面
3. 对一个简单的HTTP Request做出响应
我们在task_platform下(存放url.py和settings.py的那个目录),新建一个views.py,里面保存用来进行响应的函数。
# task_platform/views.py
from django.http import HttpResponse
def test_function(request):
return HttpResponse("Hello World!")
这个函数很简单:在接收到请求后,直接返回“Hello World!”。
接下来我们再在 task_platform/urls.py 中添加一个 url 路由:
# task_platform/urls.py
from django.contrib import admin
from django.urls import path
from task_platform import views # added
urlpatterns = [
path('admin/', admin.site.urls),
path('test/', views.test_function), # added
]
这个路由的意思是:如果 Django 接收到的URL是“test/”,比如你用浏览器访问地址 http://127.0.0.1:8000/test/ ,那么则调用views.test_function来对这个请求进行响应。
让我们将服务器运行起来试一下
$ python3 manage.py runserver
... ...
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
在浏览器里访问 http://127.0.0.1:8000/test/ ,你就能接收到Hello World啦!
4. 解析带参数的URL
比如这样一个URL: http://example.com/?var1=Django&var2=REST,它在请求 http://example.com/的时候,携带了两个参数:var1的值是"Django", var2的值是"REST"。在Django中,通过request.GET就能得到URL中的参数,比如,我们将之前的test_function修改为:
# task_platform/views.py
# ... ...
def test_function(request):
var1 = request.GET["var1"]
var2 = request.GET["var2"]
return HttpResponse("{var1} {var2}".format(var1=var1, var2=var2))
这个函数的意思是,在URL中拿到var1和var2两个参数,并将他们拼接的字符串返回。重新运行一下服务器,访问 http://127.0.0.1:8000/test/?var1=Hello&var2=World,就可以看到和之前一样的“Hello World”了。当然你也可以自由改变url中var1和var2的参数,来查看不同的返回结果。
练习:请用这种方法,在服务器端完成一个加法接口,即在接收到var1和var2后,服务器将其转化为数值,相加后返回。
5. 解析HTTP请求的body
一般,HTTP请求的报文格式如下:
<方法> <URL> <协议版本>
<其它头信息,如Host, Cookies等>
<body>
其中<方法>有GET、POST、PUT、DELETE等。协议版本现在一般都是HTTP/1.1。其它头信息包括如Host、Content-Type、Cookies等。头信息和body之间有一个空行。在GET方法中,所有的参数都是写到URL里面的,因此GET请求没有body。比如我们在上面发起的请求,其内容为:
GET /test/?var1=Hello&var2=World HTTP/1.1
Host: 127.0.0.1:8000 # 头信息
Connection: keep-alive # 头信息
... ... # 其它头信息,没有body
我们接下来要讨论的是POST方法。用户在发送POST请求的时候,可以向body里添加信息,如下面这个POST请求:
POST /test/ HTTP/1.1
... ... # 其它头信息
Hello World
最后一行就是这个POST请求的body。在Django中,我们可以通过request.body来访问这部分数据。我们将我们的test_function进行一些修改:
# task_platform/views.py
# ... ...
def test_function(request):
return HttpResponse("{var}".format(var=request.body))
然后使用Postman(一个模拟HTTP请求的工具,因为我们暂时没有前端,所以这个工具会一直用到。下载Postman请访问 https://www.getpostman.com/apps)来进行一个POST请求的模拟:
当我们点击Send后,却发现服务器返回了403 Forbidden,并且提示说“CSRF cookie not set”。这是Django出于安全考虑,要求每个POST请求都要带一个csrf_token。我们先不关注它,在settings.py里将这个功能关闭:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', 注释掉这一行,关闭CSRF
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
再试一次,我们就能重新收到Hello World了。但是格式是 b'Hello World',前面多了个b。这是因为Django将request.body理解为二进制数据序列,我们需要decode一下,来得到字符串:
# task_platform/views.py
# ... ...
def test_function(request):
return HttpResponse("{var}".format(var=request.body.decode('utf-8')))
再试一次,就正常了。
练习:尝试在POST的body中写入两个数,并完成两个数的加法后返回。