00-django | 02-处理HTTP请求
Django 处理 HTTP 请求 Hello 视图函数我们先以一个最简单的 Hello World 为例来看看 django 处理上述问题的机制是怎么样的。
绑定 URL 与视图函数当用户访问不同的网址时,Django需要知道如何处理这些网址(路由)。django 的做法是把不同的网址对应的处理函数写在一个urls.py
文件里,当用户访问某个网址时,django 就去会这个文件里找,如果找到这个网址,就会调用和它绑定在一起的处理函数(叫做视图函数)。下面是具体的做法,首先在 blog 应用的目录下创建一个 urls.py 文件,这时你的目录看起来是这样:
.
├── __init__.py
├── admin.py
├── apps.py
├── migrations
├── models.py
├── static
├── tests.py
├── urls.py #这个
└── views.py
urls.py
在 blog\urls.py 中写入这些代码:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
解释:
- 从
django.urls
模块中导入了path
函数;并从当前目录导入了views
模块。也就是上面view.py
这个文件 - 将网址和处理函数的关系作为参数传给
path
函数(网址,处理函数,处理函数的别名) - 我们本地开发服务器的域名是 http://127.0.0.1:8000, 那么当用户输入网址 http://127.0.0.1:8000 后,django 首先会把协议 http、域名 127.0.0.1 和端口号 8000 去掉,此时只剩下一个空字符串,而 '' 的模式正是匹配一个空字符串,于是二者匹配,django 便会调用其对应的
views.index
函数。
.
├── Pipfile
├── Pipfile.lock
├── blog
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── firstblog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ ├── tests.py
│ ├── urls.py # 修改的是这个
│ └── views.py
├── manage.py
编写视图函数注意在 blogproject\ 目录下(即 settings.py 所在的目录),原本就有一个 urls.py 文件,这是整个工程项目的 URL 配置文件。而我们这里新建了一个 urls.py 文件,且位于 blog 应用下。这个文件将用于 blog 应用相关的 URL 配置,这样便于模块化管理。不要把两个文件搞混了。
第二步就是要实际编写我们的 views.index 视图函数了,按照惯例视图函数定义在 views.py 文件里:
from django.http import HttpResponse
def index(request):
return HttpResponse("欢迎访问我的博客首页!")
WEB服务器的本质就是==接收用户的http请求,也就是request
,然后根据请求内容返回相应的http响应。这个request
就是 django 为我们封装好的 HTTP 请求,它是类 HttpRequest
的一个实例。然后我们便直接返回了一个 HTTP 响应给用户,这个 HTTP 响应也是 django 帮我们封装好的,它是类 HttpResponse
的一个实例,只是我们给它传了一个自定义的字符串参数。浏览器接收到这个响应后就会在页面上显示出我们传递的内容 :欢迎访问我的博客首页!
前面建立了一个 urls.py 文件,并且绑定了 URL 和视图函数 index,还要让Django知道去找这个urls.py
才行。django 匹配 URL 模式是在 blog\ 目录(即 settings.py 文件所在的目录)的 urls.py
下的,所以我们要把 firstblog 应用下的 urls.py
文件包含到 blog\urls.py
里去,打开这个文件看到如下内容:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('firstblog.urls')),
]
我们这里导入了一个 include
函数,然后利用这个函数把 firstblog 应用下的 urls.py
文件包含了进来。此外 include 前还有一个 ''
,这是一个空字符串。这里也可以写其它字符串,django 会把这个字符串和后面 include
的 urls.py
文件中的 URL 拼接。比如说如果我们这里把 '' 改成 'firstblog/',而我们在 firstblog\urls.py
中写的 URL 是 '',即一个空字符串。那么 django 最终匹配的就是 firstblog/ 加上一个空字符串,即 firstblog/。
.
├── Pipfile
├── Pipfile.lock
├── blog
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py #改的这个
│ └── wsgi.py
├── db.sqlite3
├── firstblog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
运行 pipenv run python manage.py runserver
,在浏览器输入开发服务器的地址 http://127.0.0.1:8000/, 可以看到 django 返回的内容了。
使用 django 模板系统欢迎访问我的博客首页!
写好处理 HTTP 请求和返回 HTTP 响应的视图函数,然后把视图函数绑定到相应的 URL 上。 这就是Django处理HTTP的流程。
但我们不能每次都把大段的内容传给 HttpResponse。django 对这个问题给我们提供了一个很好的解决方案,叫做模板系统。django 要我们把大段的文本写到一个文件里,然后 django 自己会去读取这个文件,再把读取到的内容传给 HttpResponse
。
首先在我们的项目根目录(即 manage.py 文件所在目录)下建立一个名为templates
的文件夹,用来存放我们的模板。然后在templates\
目录下建立一个名为 blog
的文件夹,用来存放和 blog 应用相关的模板。在 templates\blog
目录下建立一个名为 index.html
的文件,此时你的目录结构应该是这样的:
.
├── Pipfile
├── Pipfile.lock
├── blog
├── db.sqlite3
├── firstblog
├── manage.py
└── templates
└── blog
└── index.html
在index.html
中写入:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ welcome }}</h1>
</body>
</html>
用 {{ }}
包起来的变量叫做模板变量。django 在渲染这个模板的时候会根据我们传递给模板的变量替换掉这些变量。最终在模板中显示的将会是我们传递的值。
模板写好了,还得告诉 django 去哪里找模板,在 settings.py
文件里设置一下模板文件所在的路径。在 settings.py 找到 TEMPLATES 选项,它的内容是这样的:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #修改成这样
'APP_DIRS': True,
'OPTIONS': {
其中 DIRS
就是设置模板的路径,在[]
中写入 os.path.join(BASE_DIR, 'templates')
这里 BASE_DIR
是 settings.py
在配置开头有定义,记录的是工程根目录 查找路径。在这个目录下有模板文件所在的目录 templates\
,于是利用os.path.join 把这两个路径连起来,构成完整的模板路径,django 就知道去这个路径下面找我们的模板了。视图函数view.py
可以改成下面这样:
from django.shortcuts import render
def index(request):
return render(request, 'blog/index.html', context={
'title': '我的博客首页',
'welcome': '欢迎访问我的博客首页'
})
调用 django 提供的 render
函数。这个函数根据我们传入的参数来构造 HttpResponse。我们首先把 HTTP 请求(request)传了进去,然后 render 根据第二个参数的值 blog/index.html 找到这个模板文件并读取模板中的内容。之后 render 根据我们传入的 context 参数的值把模板中的变量替换为我们传递的变量的值,{{ title }}
被替换成了 context 字典中 title 对应的值,同理 {{ welcome }}
也被替换成相应的值。最终,我们的 HTML 模板中的内容字符串被传递给 HttpResponse 对象并返回给浏览器(django 在 render 函数里隐式地帮我们完成了这个过程),这样用户的浏览器上便显示出了我们写的 HTML 模板的内容了。
[1] HelloGitHub-Team 仓库: https://github.com/HelloGitHub-Team/HelloDjango-blog-tutorial
https://mp.weixin.qq.com/s/A9RHHm6wRDsMzbMU9oShyQ