上一篇文章里,我们做了一个alionlineecs(阿里云线上环境服务器)的添加界面,但是要知道我们的计划里是有六个分支的,而alionlineecs仅仅是其中之一,要是每一个都这么写的话,那么views.py肯定又臭又长,充满了大量的复制片段。
对于这样的情况,我们就用一种统一的方式,把这些alionlineecs\alifuncecs\slb\rds等等这些分支当成一个变量,再自定义两个url,比如lists这个url就是展示功能,当在浏览器里输入"外网地址:8000/lists/alionlinecs"的时候,就会出现阿里线上环境服务器的展示界面;当在浏览器里输入"外网地址:8000/lists/slb"的时候,就会出现阿里负载均衡的展示界面。同时也额外设定一个add的url,当在浏览器里输入"外网地址:8000/add/alionlinecs"的时候,就会出现阿里线上环境服务器的添加界面。这样就同意好管理多了。
于是我们先编辑vim forms.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# -*- coding: UTF-8 -*-
from
django.forms
import
ModelForm
from
.models
import
alionlineECS,alifuncECS,ksonlineECS,ksfuncECS,SLB,RDS
#定义ECS的Form,Form名字为 模式名+Form
class
alionlineForm(ModelForm):
#自定义ModelForm的内容
class
Meta:
#该ModelForm参照Model: ECS
model
=
alionlineECS
#在Form中不显示node_signer这个字段
exclude
=
[
'ecs_signer'
]
class
alifuncForm(ModelForm):
class
Meta:
model
=
alifuncECS
exclude
=
[
'ecs_signer'
]
class
ksonlineForm(ModelForm):
class
Meta:
model
=
ksonlineECS
exclude
=
[
'ecs_signer'
]
class
ksfuncForm(ModelForm):
class
Meta:
model
=
ksfuncECS
exclude
=
[
'ecs_signer'
]
class
SLBForm(ModelForm):
class
Meta:
model
=
SLB
exclude
=
[
'slb_signer'
]
class
RDSForm(ModelForm):
class
Meta:
model
=
RDS
exclude
=
[
'rds_signer'
]
|
然后把urls.py进行一下整顿:
1
2
3
4
5
6
7
8
|
from
django.conf.urls
import
url
from
django.contrib
import
admin
import
Online.views
urlpatterns
=
[
url(r
'^admin/'
,admin.site.urls),
url(r
'^lists/(?P<table>\w+)/$'
,Online.views.lists,name
=
'lists'
),
url(r
'^add/(?P<table>\w+)/$'
,Online.views.add,name
=
'add'
),
]
|
最麻烦的地方就是views.py,这个变动比较大了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# -*- coding: UTF-8 -*-
from
django.shortcuts
import
render,redirect
from
.models
import
alionlineECS,alifuncECS,ksonlineECS,ksfuncECS,SLB,RDS
from
forms
import
alionlineForm,alifuncForm,ksonlineForm,ksfuncForm,SLBForm,RDSForm
def
lists(request,table):
#不同的需求跳到不同的界面
if
table
=
=
'alionlineECS'
:
data
=
alionlineECS.objects.
all
()
list_template
=
'alionlineECS_list.html'
if
table
=
=
'alifuncECS'
:
data
=
alifuncECS.objects.
all
()
list_template
=
'alifuncECS_list.html'
if
table
=
=
'ksonlineECS'
:
data
=
ksonlineECS.objects.
all
()
list_template
=
'ksonlineECS_list.html'
if
table
=
=
'ksfuncECS'
:
data
=
ksfuncECS.objects.
all
()
list_template
=
'ksfuncECS_list.html'
if
table
=
=
'SLB'
:
data
=
SLB.objects.
all
()
list_template
=
'slb_list.html'
if
table
=
=
'RDS'
:
data
=
RDS.objects.
all
()
list_template
=
'rds_list.html'
#建立一个context,将值传递到对应的页面
context
=
{
'data'
:data,
}
#跳转到相应页面,并将具体的值传递过去
return
render(request,list_template,context)
def
add(request,table):
#根据提交的请求不同,获取来自不同Form的表单数据
if
table
=
=
'alionlineECS'
:
form
=
alionlineForm(request.POST
or
None
)
if
table
=
=
'alifuncECS'
:
form
=
alifuncForm(request.POST
or
None
)
if
table
=
=
'ksonlineECS'
:
form
=
ksonlineForm(request.POST
or
None
)
if
table
=
=
'ksfuncECS'
:
form
=
ksfuncForm(request.POST
or
None
)
if
table
=
=
'SLB'
:
form
=
SLBForm(request.POST
or
None
)
if
table
=
=
'RDS'
:
form
=
RDSForm(request.POST
or
None
)
#判断form是否有效
if
form.is_valid():
#创建实例,需要做些数据处理,暂不做保存
instance
=
form.save(commit
=
False
)
#将登录用户作为登记人
if
table
=
=
'alionlineECS'
:
instance.ecs_signer
=
request.user
if
table
=
=
'alifuncECS'
:
instance.ecs_signer
=
request.user
if
table
=
=
'ksonlineECS'
:
instance.ecs_signer
=
request.user
if
table
=
=
'ksfuncECS'
:
instance.ecs_signer
=
request.user
if
table
=
=
'SLB'
:
instance.slb_signer
=
request.user
if
table
=
=
'RDS'
:
instance.rds_signer
=
request.user
#保存该实例
instance.save()
#跳转至列表页面
return
redirect(
'lists'
,table
=
table)
#创建context来集中处理需要传递到页面的数据
context
=
{
'form'
: form,
}
#如果没有有效提交,则仍留在原来页面
return
render(request,
'add.html'
,context)
|
上面我们写了很多个html,那么现在就要一个一个的补全这些html,比如alionlineECS_list.html,这里放上我们需要对外展示的节点,注意要跟model.py的各项一一对应:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<
meta
charset
=
"UTF-8"
>
<
title
></
title
>
</
head
>
<
body
>
<
table
>
<
tr
>
<
th
>云服务器名称</
th
>
<
th
>云服务器类型</
th
>
<
th
>云服务器内网地址</
th
>
<
th
>云服务器外网地址</
th
>
<
th
>云服务器外网带宽</
th
>
<
th
>云服务器配置</
th
>
<
th
>备注</
th
>
<
th
>登记人</
th
>
</
tr
>
{% for item in data %}
<
tr
>
<
td
>{{ item.ecs_name }}</
td
>
<
td
>{{ item.ecs_type }}</
td
>
<
td
>{{ item.ecs_inip }}</
td
>
<
td
>{{ item.ecs_outip }}</
td
>
<
td
>{{ item.ecs_ipwidth }}</
td
>
<
td
>{{ item.ecs_spec }}</
td
>
<
td
>{{ item.ecs_remarks }}</
td
>
<
td
>{{ item.ecs_signer }}</
td
>
</
tr
>
{% endfor %}
</
table
>
</
body
>
</
html
>
|
而SLB.html就长这个样子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<!DOCTYPE html>
<
html
>
<
head
lang
=
"en"
>
<
meta
charset
=
"UTF-8"
>
<
title
></
title
>
</
head
>
<
body
>
<
table
>
<
tr
>
<
th
>负载均衡名称</
th
>
<
th
>网络类型</
th
>
<
th
>转发规则</
th
>
<
th
>ip地址</
th
>
<
th
>负载均衡协议</
th
>
<
th
>前端端口</
th
>
<
th
>后端端口</
th
>
<
th
>负载均衡协议</
th
>
<
th
>前端端口</
th
>
<
th
>后端端口</
th
>
<
th
>登记人</
th
>
<
th
>备注</
th
>
</
tr
>
{% for item in data %}
<
tr
>
<
td
>{{ item.slb_name }}</
td
>
<
td
>{{ item.slb_type }}</
td
>
<
td
>{{ item.slb_algorithm }}</
td
>
<
td
>{{ item.slb_ip }}</
td
>
<
td
>{{ item.slb_protocol }}</
td
>
<
td
>{{ item.slb_fport }}</
td
>
<
td
>{{ item.slb_bport }}</
td
>
<
td
>{{ item.slb_protocol2 }}</
td
>
<
td
>{{ item.slb_fport2 }}</
td
>
<
td
>{{ item.slb_bport2 }}</
td
>
<
td
>{{ item.slb_signer }}</
td
>
<
td
>{{ item.slb_remarks }}</
td
>
</
tr
>
{% endfor %}
</
table
>
</
body
>
</
html
>
|
RDS.html写成这个样子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html>
<
html
>
<
head
lang
=
"en"
>
<
meta
charset
=
"UTF-8"
>
<
title
></
title
>
</
head
>
<
body
>
<
table
>
<
tr
>
<
th
>数据库名称</
th
>
<
th
>数据库类型</
th
>
<
th
>mysql版本</
th
>
<
th
>数据库规格</
th
>
<
th
>备注</
th
>
<
th
>数据库地址</
th
>
<
th
>存储空间</
th
>
<
th
>登记人</
th
>
</
tr
>
{% for item in data %}
<
tr
>
<
td
>{{ item.rds_name }}</
td
>
<
td
>{{ item.rds_type }}</
td
>
<
td
>{{ item.rds_mysql }}</
td
>
<
td
>{{ item.rds_spec }}</
td
>
<
td
>{{ item.rds_remark }}</
td
>
<
td
>{{ item.rds_ip }}</
td
>
<
td
>{{ item.rds_status }}</
td
>
<
td
>{{ item.rds_signer }}</
td
>
</
tr
>
{% endfor %}
</
table
>
</
body
>
</
html
>
|
这个时候我们启动django来到浏览器里,在地址栏输入:外网地址:8000/lists/alionlinecs,就会看到之前的那个添加“阿里云线上服务器”的界面,如图:
在点击了提交之后,就会看到地址栏里的add变成了lists,达到了我们的预期目标:
在这篇文章的最后,我直接复制了http://blog.csdn.net/alex_chen_16/article/details/50850435 里对url处理请求的原理简述,留作备份和日后改进的参考。
1. Django处理请求的方式
1) Django通过URLconf模块来进行判断。通常情况下,这就是ROOT_URLCONF配置的价值,但是如果请求携带了一个urlconf的属性(通常被中间件设置),那么这个被携带的urlconf将会替代ROOT_URLCONF的配置。
2) Django会调用Python模块并寻找各种urlpatterns。这是一个属于django.conf.urls.url()实例的python列表。
3) Django会遍历每个URL pattern,自上而下,并且选取收割匹配请求URL的pattern。
4) 一旦匹配某个url pattern的正则表达式,Django将导入并调用相关的view(这是一个简单的python函数,或者是一个class-based view)
这个view将会传递下列参数:
l 一个HttpRequest的实例
l 如果匹配了URL中一个no named group,那么参数将会按根据URL中的位置一一对应
l 如果匹配了URL中一个named group,且参数传递是通过named group来匹配的,那么参数将会被指定的kwargs代替。
5) 如果没有任何一个正则表达式被匹配,那么Django会抛出异常,并报错。
2. URL中的named group
URL可以通过named group方式传递指定参数,语法为: (?P<name>pattern), name 可以理解为所要传递的参数的名称,pattern代表所要匹配的模式。例如,
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
那么year,month将会对应views传递过来的year,month的值,而后面紧跟的则代表正则表达匹配的模式。
3. URL的反向解析
通常来说在处理完一个表单之后,网页会发生跳转。通常写URL我们都避免硬编码,这样不方便后期的调整。通常我们需要从URL获取两种内容,最主要是view能够通过URL获取一些标识并处理,另一些信息则是传递过来的参数。
Django提供了一种解决方案,URL mapper是与URL设计一一对应。你可以通过URLconf来实现,并反向使用它。例如:
由用户通过浏览器发起URL请求,调用view,并将URL中的参数传递给view
通过view并附上相应参数,找到相应匹配的URL。
后者我们称之为对URLs的反向解析。反向解析的例子,
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
Django在不同的层次也提供了一些工具来实现URL的反向解析。
在template中:使用url标签
在python中:使用django.core.urlresolvers.reverse()函数
在更高层次处理model实例时,可以使用get_absolute_url()方法