数据库的基本设置我们已经配置完成,接下来就是我们让django处理http请求 。web的交互过程其实就是http请求和响应的 过程。我们在使用浏览器 登陆网址的时候,输入网址后,浏览器会我们像要访问的网址打包成一个http请求,并发给该网址对应的服务器,服务器处理了http请求,并生成一段http响应给浏览器,,然后浏览器解读这段http生成相对应的网页内容给我们。
django作为一个web框架,所要做的事情其实就是,接受并且处理http请求,返回http响应。
那我们可以想一下,django是怎样接收http请求,是怎么处理http请求,是怎么生成http响应 。
我想大致说一下,其最基本的执行过程,当我们开启了本地服务器以后,我们试着访问django帮我们生成的网址,这个访问请求就会被浏览器打包成http请求发送给本地的web服务器,这个请求会先去blogproject 下的blogproject下的urls文件中匹配,我说一下这个urls文件的内容,根据在urls里面匹配到的东西,又会进入我们在 blog下创建的views文件。根据这个文件里面的函数,我们得到 对应的html页面。简单的大致就是这样。
接下来我来仔细的分析一下这个过程。
首先django需要知道当 用户访问不同的网址时,应该如何 处理这些不同的网址,也就是我们说的路由。django的做法是把不同的网址对应的处理函数写在一个urls.py文件里,当用户访问某个网址时候,django就去这个文件里面找,如果找到这个网址,就会调用和它绑定在一起的处理函数。(叫做 视图函数)
下面是具体的做法,首先在blog应用的目录下创建一个urls.py文件,这时你的目录看起来是这样:
blog\
__init__.py
admin.py
apps.py
migrations\
0001_initial.py
__init__.py
models.py
tests.py
views.py
urls.py
在blog\urls.py中写入这些代码:
blog/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
我们首先从 django.conf.urls 导入了 url 函数,又从当前目录下导入了 views 模块。然后我们把网址和处理函数的关系写在了 urlpatterns 列表里。
绑定关系的写法是把网址和对应的处理函数作为参数传给 url 函数(第一个参数是网址,第二个参数是处理函数),另外我们还传递了另外一个参数 name,这个参数的值将作为处理函数 index 的别名,这在以后会用到。
注意这里我们的网址是用正则表达式写的,Django 会用这个正则表达式去匹配用户实际输入的网址,如果匹配成功,就会调用其后面的视图函数做相应的处理。
比如说我们本地开发服务器的域名是 http://127.0.0.1:8000,那么当用户输入网址 http://127.0.0.1:8000 后,Django 首先会把协议 http、域名 127.0.0.1 和端口号 8000 去掉,此时只剩下一个空字符串,而 r’^$’ 的模式正是匹配一个空字符串(这个正则表达式的意思是以空字符串开头且以空字符串结尾),于是二者匹配,Django 便会调用其对应的 views.index 函数。
自己观察一下,在项目根目录的 blogproject\ 目录下(即 settings.py 所在的目录),原本就有一个 urls.py 文件,这是整个工程项目的 URL 配置文件。而我们这里新建了一个 urls.py 文件,且位于 blog 应用下。这个文件将用于 blog 应用相关的 URL 配置。不要把两个文件搞混了。
编写视图函数
第二步就是要实际编写我们的 views.index 视图函数了,按照惯例视图函数定义在 views.py 文件里:
blog/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("欢迎访问我的博客首页!")
我们前面说过,Web 服务器的作用就是接收来自用户的 HTTP 请求,根据请求内容作出相应的处理,并把处理结果包装成 HTTP 响应返回给用户。
这个两行的函数体现了这个过程。它首先接受了一个名为 request 的参数,这个 request 就是 Django 为我们封装好的 HTTP 请求,它是类 HttpRequest 的一个实例。然后我们便直接返回了一个 HTTP 响应给用户,这个 HTTP 响应也是 Django 帮我们封装好的,它是类 HttpResponse 的一个实例,只是我们给它传了一个自定义的字符串参数。
浏览器接收到这个响应后就会在页面上显示出我们传递的内容 :欢迎访问我的博客首页!
配置项目 URL
还差最后一步了,我们前面建立了一个 urls.py 文件,并且绑定了 URL 和视图函数 index,但是 Django 并不知道。Django 匹配 URL 模式是在 blogproject\ 目录(即 settings.py 文件所在的目录)的 urls.py 下的,所以我们要把 blog 应用下的 urls.py 文件包含到 blogproject\urls.py 里去,打开这个文件看到如下内容:
blogproject/urls.py
"""
一大段注释
"""
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
所以我们要进行修改,让 django知道这个url
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('blog.urls')),
]
再导入的url后面加个include
利用这个include函数,然后利用这个函数把blog应用下的urls文件包含进来,include前面是匹配的一个空字符串,这里也可以写其他字符串,以后我们会遇到,再讲。django会把这个字符串和后面include的urls文件中的url拼接。比如说我们这里把r’ ‘改成r’blog/’,而我们在 blog下的urls中写的是r’^$’,就是一个空字符串。那么django最终匹配的就是blog/加上一个空字符串,即blog/。
运行结果
激活虚拟环境,运行 python manage.py runserver 打开开发服务器,在浏览器输入开发服务器的地址 http://127.0.0.1:8000/,可以看到 Django 返回的内容了。
欢迎访问我的博客首页!
这基本上就上 Django 的开发流程了,写好处理 HTTP 请求和返回 HTTP 响应的视图函数,然后把视图函数绑定到相应的 URL 上。
但是等一等!我们看到在视图函数里返回的是一个 HttpResponse 类的实例,我们给它传入了一个希望显示在用户浏览器上的字符串。但是我们的博客不可能只显示这么一句话,它有可能会显示很长很长的内容。比如我们发布的博客文章列表,或者一大段的博客文章。我们不能每次都把这些大段大段的内容传给 HttpResponse。
Django 对这个问题给我们提供了一个很好的解决方案,叫做模板系统。Django 要我们把大段的文本写到一个文件里,然后 Django 自己会去读取这个文件,再把读取到的内容传给 HttpResponse。让我们用模板系统来改造一下上面的例子。
首先在我们的项目根目录(即 manage.py 文件所在目录)下建立一个名为 templates 的文件夹,用来存放我们的模板。然后在 templates\ 目录下建立一个名为 blog 的文件夹,用来存放和 blog 应用相关的模板。
当然模板存放在哪里是无关紧要的,只要 Django 能够找到的就好。但是我们建立这样的文件夹结构的目的是把不同应用用到的模板隔离开来,这样方便以后维护。我们在 templates\blog 目录下建立一个名为 index.html 的文件,此时你的目录结构应该是这样的:
blogproject\
manage.py
blogproject\
__init__.py
settings.py
...
blog\
__init__.py
models.py
,,,
templates\
blog\
index.html
再一次强调 templates\ 目录位于项目根目录,而 index.html 位于 templates\blog 目录下,而不是 blog 应用下,如果弄错了你可能会得到一个TemplateDoesNotExist 异常。如果遇到这个异常,请回来检查一下模板目录结构是否正确。
在 templates\blog\index.html 文件里写入下面的代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}title>
head>
<body>
<h1>{{ welcome }}h1>
body>
html>
这是一个标准的HTML文档,只是里面有两个比较奇怪的地方:{{title}},{{welcome}}。这是django规定的语法,用{{}}包起来的变量叫做模板变量。django在渲染这个模板的时候会根据我们传递给模板 的变量替换掉这些变量。最终在模板中显示的将会是我们传递的值。
注意:index.html必须 以utf-8的编码格式保存,且小心不要往里面添加一些特殊字符,否则 极有可能得到一个UnicodedecodeError这样的错误。
模板写好了,我们还得 告诉django去哪里找模板 ,在settings.py文件里设置一下模板文件所在的路径。在settings.py找到TEMPLATES选项,里面的内容是这样的:
blogproject/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
其中DIRS就是设置模板的路径,在中括号中写入os.path.join(BASE_DIR,’templates’),就像下面这样:
'DIRS': [os.path.join(BASE_DIR, 'templates')],
这里的BASE_DIR是settings.py在配置开头前面定义的变量,记录的是工程根目录blogproject\的值。在这个目录下有模板文件所在的目录templates\,于是利用os.path.join()把这两个路径连接起来,下有模板文件所在的目录 templates\,于是利用os.path.join 把这两个路径连起来,构成完整的模板路径,Django 就知道去这个路径下面找我们的模板了。
视图函数可以改一下了:
blog/views.py
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'blog/index.html', context={
'title': '我的博客首页',
'welcome': '欢迎访问我的博客首页'
})
这时候当我们再次请求访问http://127.0.0.1:8000,返回的就是这个html页面,并且里面设置的模板变量也已经生效。我们首先把http请求传了进去,然后render根据第二个参数的值blog/index.html找到这个模板文件并读取模板中的内容。之后render根据我们传入的context参数的值模板中的变量替换为我们传递的变量的值,{{title}}被替换成了context字典中的title对应的数值。同理welcome