本博客将会涉及:
- 路由映射
- 视图编写
环境:
- Django2.2.10
- python3.5
在django中,项目的组织结构为一个项目包含多个应用,一个应用对应一个业务模块。也就是说,多个功能模块,可以分开多个应用去逐个编写,逐个击破。
一、路由映射
在上一篇文章中介绍了 Django 的项目和应用,最后使用 manage.py 工具运行测试服务器在本地的 8000 端口之上。在打开 /admin 链接的时候,网站自动跳转到了 Django 的后台,究其缘由,knowledge_gragh_qa 目录下的 urls.py 文件起了至关重要的作用, 我们来分析一下这个 urls.py 文件。
在 urls.py 文件的头部,一共引入了两个模块,以及定义了一个列表将其赋值给变量 urlpatterns:
其中,
- 第一行代码中引入的 admin 模块,则是 Django 自带的管理后台的总模块。
- 第二行代码引用的 url 模块,将匹配到的 URL 映射到 Django 项目中的某个模块。
- 在使用Django的时候,多次遇到urls与path,不知道两者有什么区别。下面简单介绍一下两者
- 在django>=2.0的版本,urls.py中的django.conf.urls已经被django.urls所取代。其中最大的改变如下:import urls被import path所取代如果是路径需要在路径的后面加上一个斜杠 /
- 在2.0中,它推荐使用的是path模块,这里要注意的是,如果要使用正则,则要引入re_path,from django.urls import path, re_path
这里面的正则写法,有点意思,一定要使用()把正则包起来,然后用?P正式表达式 这种形式来表式。 - 在Python正则表达式中,命名式分组语法为
(?P<name>pattern)
,其中name为名称, pattern为待匹配的模式。 - 第三行的变量 urlpatterns,它是一个 url() 的实例列表。
在代码中可以发现,文件中引入的两个模块都在定义的列表 urlpatterns 中进行了调用,其中,admin.site.urls 方法作为第二个参数传递给了 url() 方法,而 url 方法中的 第一个参数,用来匹配以 admin 开头的字符串。
简单的几行代码似乎没有什么玄妙,但是这其实已经揭示了 Django 处理 Http 请求的过程。
当一个用户请求一个页面的时候,Django 加载 urls.py 文件并解析 urlpatterns 列 表,然后将 urlpatterns 列表中的正则表达式与请求的 url 进行匹配(比如本例中的 /admin),如果匹配到了,就将正则表达式对应的视图返回出去(本例中的 admin.site.urls),否则,就会抛出一个 404 错误的异常。
而 Django 为什么会知道使用 knowledge_gragh_qa 文件夹下的 urls.py 文件呢?因为默认已经 在 settings.py 文件中通过关键词参数 ROOT_URLCONF 指定了,我们可以打开 settings.py 文件查看一下,结果如下图所示:
结合起来,可以从中发现 Django 面对一个 url 时的完整处理流程,以 /admin 为 例:
• 浏览器请求 /admin;
• Django 查看 settings.py 文件中的 ROOT_URLCONF 配置,找到路由映射文件— —videolearn 目录下的 urls.py;
• 从路由映射文件中匹配 /admin 路径——'admin/';
• 如果匹配到路径,则调用相应的视图函数——admin.site.urls;
• 视图函数将一个结果作为 HTTP 响应返回给浏览器——浏览器呈现的 Django 后台界面。
所以在 Django 中设置路由映射是很简单的事。
在 urls.py 文件的 urlpatterns 列表中添加匹配的路由和对应的视图函数即可,其结构 如下所示:
path(正则表达式, 业务处理视图)
二、视图
参考文献:
Django 2.2 官方文档:https://docs.djangoproject.com/zh-hans/2.2/intro/tutorial01/
Django 2.1.7 创建项目:https://www.jianshu.com/p/e690de75d48b
在这里又引出来了一个概念——视图函数。什么是视图?也就是具体的逻辑处理函数, 用来接受 Web 请求并返回 Web 响应。比如上面的 Django 后台的视图 admin.site.urls,接受请求,在发现我们没有登录的时候,返回一个表单来进行登录。
在 Django 中,约定俗成将视图函数放置在应用(App)文件夹下的 views.py 文件 中。
在使用 startapp 命令创建应用的时候,views.py 文件就已经被创建好了,我们打开看看,其内容如下所示:
目前这个文件中只引入了一个模块 render,render 用于将一个 Django 模板作为 HTTP 响应返回给浏览器,在接下来要编写的视图函数中,会经常使用到它。当前我们 还没有使用到模板,所以需要另外一个方法——HttpResponse。
HttpResponse()方法用于将一个字符串作为 HTTP 响应返回给浏览器,在本篇中主要 使用 HttpResponse 这个方法来返回 HTTP 响应。
让我们开始编写第一个视图吧。打开 knowledge_qa/views.py,把下面这些 Python 代码输入进去:
def index(request):
return HttpResponse("这是首页")
看看创建的这个视图函数 index(),该函数接收 request 请求实例作为参数,然后返回 了一个字符串作为响应。
每一个视图函数都必须至少有一个参数,那就是名为 request 的对象,这是 HTTP 请 求的实例,包含了 HTTP 请求的所有信息。虽然在此没有使用到它,但是也必须作为 第一个参数传递给视图函数。
结合上面介绍的路由映射的知识,如果想看见效果,我们需要将一个 URL 映射到它——这就是我们需要 URLconf 的原因了,将这个首页 index 视图函数映射到一条路由上,为了创建 URLconf,请在 knowledge_qa 目录里新建一个 urls.py 文件。你的应用目录现在看起来应该是这样:
在 knowledge_qa /urls.py 中,输入如下代码:
from django.urls import path
from . import views
urlpatterns = [
path('',views.index,name='index'),
]
下一步是要在根 URLconf 文件中指定我们创建的 knowledge_qa.urls 模块。在 knowledge_gragh_qa/urls.py 文件的 urlpatterns 列表里插入一个 include(), 如下:
from django.contrib import admin
from django.urls import include,path #增加导入include方法
urlpatterns = [
path('knowledge_qa/',include('knowledge_qa.urls')),#导入knowledge_qa应用的urls.py
path('admin/', admin.site.urls),
]
设计 include()
的理念是使其可以即插即用。因为应用有它自己的 URLconf( knowledge_qa/urls.py
),他们能够被放在 "/knowledge_qa/",或者其他任何路径下,这个应用都能够正常工作。
现在把 index 视图添加进了 URLconf。可以验证是否正常工作,运行下面的命令:
python3 manage.py runserver
用你的浏览器访问 http://localhost:8000/knowledge_qa/,你应该能够看见 "这是首页" ,这是你在 index
视图中定义的。
显示的是我们在 index() 函数中使用 HttpResponse 返回的字符串。
这其实就是一个最简单的 HTTP 请求与响应:客户端请求根路径,服务器返回一个字 符串作为响应。
到这第一个视图就创建成功啦~
例子:创建一个在线的视频学习网站,所以首先来创建一些网站相关的视图函数。
首先,创建一个首页的视图函数,用于处理访问首页的请求,这是网站的首页:
#首页
def index(request):
return HttpResponse("这是首页")
结合上面介绍的路由映射的知识,将这个首页 index 视图函数映射到一条路由上,在 urls.py 文件中进行修改:
在Django2.0中,它推荐使用的是path模块,这里要注意的是,如果要使用正则,则要引入re_path,from django.urls import path, re_path
在 video/urls.py 中,输入如下代码:
from django.urls import path,re_path
from . import views
urlpatterns = [
re_path(r'^video/$', views.index, name='index'),
]
下一步是要在根 URLconf 文件中指定我们创建的 video.urls 模块。在 videolearn/urls.py 文件的 urlpatterns 列表里插入一个 include(), 如下:
from django.contrib import admin
from django.urls import include,re_path,path #增加导入include方法
urlpatterns = [
re_path(r'',include('video.urls')),#导入video应用的urls.py
re_path(r'^admin/', admin.site.urls),
]
现在把 index 视图添加进了 URLconf。可以验证是否正常工作,运行下面的命令:
python3 manage.py runserver
新建一条路由映射就是这么简单,运行一下测试服务器,访问服务器的首页,结果如下图所示:
按照上面的模式,我们继续在 views.py 文件中创建更多的视图函数:
# 视频详情页
def videoDetail(request, vid):
return HttpResponse("这是{0}视频详情页".format(vid))
# 观看历史页
def viewHistory(request):
return HttpResponse("这是观看历史页")
# 视频分类页
def videoCate(requests, cateid):
return HttpResponse("这是{0}分类".format(cateid))
# 登录页面
def logIn(request):
return HttpResponse("这是登录页")
# 注册页面
def register(request):
return HttpResponse("这是注册页")
我们创建了一个视频详情页视图、一个观看历史页视图、视频分类页视图、登录页面视 图和注册页面视图,这些暂时是我们目前想到的,根据网站功能的添加和完善,可以继 续在其中创建更多的视图函数。
接着,在 video/urls.py 文件中将视图函数与 URL 进行映射,添加 url 正则匹配映射代码到 urlpatterns 列表中,最终结果为:
urlpatterns = [
re_path(r'^video/$', views.index, name='index'),
re_path(r'^video/(?P<vid>\d+)/$', views.videoDetail, name='videoDetail'),
re_path(r'^history/$', views.viewHistory, name='viewHistory'),
re_path(r'^cate/(?P<cateid>\d+)/$', views.videoCate, name='videoCate'),
re_path(r'^login/$', views.logIn, name='logIn'),
re_path(r'^register/$', views.register, name='register'),
]
最后,运行测试服务器,查看一下我们创建的视图函数和 URL 映射是否成功。
视频详情 URL 映射
首先是视频详情 URL,因为网站中会有很多个视频,每个视频的 URL 链接地址都应 该是唯一的,所以使用正则表达式:
r'^video/(?P<vid>\d+)/$
对 URL 进行匹配,同时通过命名组(?Ppattern)为参数进行了命名,访问 URL 链 接:http://127.0.0.1:8000/video/2/,结果会将 URL 中的 2 作为参数传递给视图函数 videoDetail 的 vid,结果如下图所示:
观看历史 URL 映射
观看历史的 URL 映射,我们直接对 URL 匹配 history:
r'^history/$'
访问 URL 链接:http://127.0.0.1:8000/history/,结果显示了 viewHistory 视图函数中返回的内容,如下图所示:
视频分类 URL 映射
视频分类的 URL 映射与视频详情的 URL 映射类似,都使用了命名组为视图函数传递 参数值:
r'^cate/(?P<cateid>\d+)/$'
访问 URL 链接:http://127.0.0.1:8000/cate/3/,结果会将 URL 中的 2 作为参数传递 给视图函数 videoCate 的 cateid,结果如下图所示:
登录和注册 URL 映射
登录和注册的 URL 地址直接匹配关键字 “login” 和 “register”:
r'^login/$'r'^register/$'
访问 URL 地址 http://127.0.0.1:8000/login/,会调用视图函数 logIn() 进行响应,结果如图 2-6 所示:
访问 URL 地址 http://127.0.0.1:8000/register/,会调用视图函数 register() 进行响 应,结果如图 2-7 所示:
这样,我们创建的六个视图函数,以及调用它们的 URL 路由映射就已经编写好了,但是现在的视图函数仅仅返回了一个字符串作为 HTTP 响应,而在实际的规划中,我们是需要从数据库中检索出数据并作为 HTTP 响应返回给浏览器的。
题外话:启动开发web服务
在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。
运行服务器命令如下:
python3 manage.py runserver ip:port
例:
python3 manage.py runserver
可以不写IP和端口,默认IP是127.0.0.1,默认端口为8000。