Mapz's Blog

可以递归的函数指针

Django项目开发(二)View层

原文地址:Mapz的blog

前文目录:

  1. Django项目的搭建
  2. Django项目开发(一)

前面我们已经创建好了我们的数据库表,也可以管理我们的数据内容了,下面就应该是如何来展示我们的网站内容

基本方式

前面大家看例子的时候已经看到了,我们在 views.py 中,写一个函数,返回一个HttpRespnse对象,参数为字符串hello world,并在 urls.py 里面配置好他的路由,就可以通过浏览器来访问我们的页面了,没错,这就是一个最简单的view,返回一个HttpRespnse对象,只包含一段字符串到浏览器。


Url路由

1
2
3
urlpatterns = [
url(r'^$', views.index, name='index'),
]

每增加一个路由,我们都在urlpatterns里面增加一个url()函数生成的对象

我们可以看看这个函数原型

1
def url(regex, view, kwargs=None, name=None, prefix='')
  1. 第一个参数为浏览器访问的url路由正则表达式
  2. 第二个参数是处理这个请求的view
  3. 第三个参数是显式的传入参数
  4. 第四个参数是这个url的名称,常用于渲染模版的时候,避免改需求后模版上url写死了要到处修改用(写模版的时候不要写死跳转的url,而是用name来渲染是一个良好的习惯),另外,后面我们会知道,一个视图view经常对应很多pattern,用name也可在使用的时候加以区分
  5. prefix 在view上加上前缀,一般不会用到这个

正则表达式中用小括号括起来的内容,会作为参数传入到view中的处理函数中

为了测试路由中各种用法,我们创建一个文件专门放我们的测试view

隐式的传参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# test_views.py
# -*-coding:utf-8 -*-
from django.http import HttpResponse


def add(request,p1,p2):
p1 = float(p1)
p2 = float(p2)
return HttpResponse("%f + %f = %f" % (p1,p2,p1+p2))



# urls.py
from . import views,test_views
testPatterns = [
url(r'^add(\d+)and(\d+)/$', test_views.add, name='add'),
]

urlpatterns.extend(testPatterns)

我们看url中有两个参数

当我们访问 http://127.0.0.1:8000/qk_deploy/add1and2/ 的时候,他们被顺序的传入test_view.add函数的p1和p2

需要注意的是,通过正则穿进去的参数,都是字符串形式的,要转型需要我们在代码中处理

最后我们在浏览器中得到了返回

1.000000 + 2.000000 = 3.000000

显式的传参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# test_views.py
def southparkB(request,stan_power,cartman_power):
stan_power = float(stan_power)
cartman_power = float(cartman_power)
return HttpResponse('Stan win' if stan_power > cartman_power else 'Cartman win')



# urls.py
testPatterns = [
...
url(r'^southpark-b/stan(?P<stan_power>\d+)/cartman(?P<cartman_power>\d+)/$', test_views.southparkB,name='southparkB')
]

urlpatterns.extend(testPatterns)

用括号括起来的部分依然是参数,但是我们用__?P<参数名>__来传递参数
然后在 test_view.southparkB 中,用相同的参数名来取出

访问

http://127.0.0.1:8000/qk_deploy/southpark-b/stan19/cartman10/

获得结果

Stan win


结合数据层使用

1
2
3
4
5
6
7
8
9
10
11
# test_views.py
def project_list(request):
p_list = Project.objects.order_by('project_name')
output = ', '.join([q.project_name for q in p_list])
return HttpResponse(output)

#urls.py
testPatterns = [
...
url(r'^projectlist/$',test_views.project_list,name='project_list'),
]

访问 http://127.0.0.1:8000/qk_deploy/projectlist/

可以看到打印出了我们已经创建的项目列表


加入模版系统

我们现在已经可以输出我们需要的内容到页面了,但是还不够美观,我们想要输出的是一个页面,而不是简单的字符串。

这时候我们就要用到 Django 的服务端渲染-模版技术

题外话:如果你想使用前后端分离

现在前后端分离的开发方式比较热门,笔者也研究过 vue.js 前端框架

要实现前后端分离,我们的后端渲染就算是用不上啦,至于业务逻辑,也需要放到前端来处理,view也不用处理业务逻辑了

我们只需要把API接口做好就可以了

我们只需要保留Django的controller部分,也就是urlconf这一块

这样一来做到了前后端分离

二来呢,django可以是很灵活的,同一个网站你可以部分页面采用 vue 部分采用 react,部分用django模版来渲染也行呀~

我们的项目将会基于vue.js 2来进行开发,搭建将在后面的文章中详细解说

在这之前,我们还是先简单讲讲 Django 自身的模版系统

创建模版

我们在app目录下创建templates目录

模版的具体设置在settings中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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',
],
},
},
]

当 APP_DIRS 为 True 的时候,Django会所有已经安装了的APP目录下的templates中寻找模版

我们继续在templates目录下创建目录qk_deploy目录,并在里面创建project_list.html

1
2
3
4
5
6
7
8
9
{% if p_list %}
<ul>
{% for p in p_list %}
<li>{{ p.project_name }}</li>
{% endfor %}
</ul>
{% else %}
<p>还没有创建项目</p>
{% endif %}

修改我们的view

1
2
3
4
5
6
7
8
9
10
11
12
# test_views.py
from django.template import loader

...

def project_list(request):
p_list = Project.objects.order_by('project_name')
template = loader.get_template('qk_deploy/project_list.html')
context = {
'p_list':p_list,
}
return HttpResponse(template.render(context,request))

重新访问 http://127.0.0.1:8000/qk_deploy/projectlist/

我们会发现我们的列表已经按模版的形式重新渲染了

  • 项目1
  • 项目2
  • 等等

render还可以简写为

1
2
3
4
5
6
7
8
from django.shortcuts import render
...
def project_list(request):
p_list = Project.objects.order_by('project_name')
context = {
'p_list':p_list,
}
return HttpResponse(render(request,'qk_deploy/project_list.html',context))

其他模版相关内容

我们这里就不赘述其他的 django 模版相关的内容了

有兴趣可以参考 官方教程