天天看点

Django运维后台的搭建之三:用url去精细定制与反向解析

上一篇文章里,我们做了一个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

<code># -*- coding: UTF-8 -*-  </code>

<code>from</code> <code>django.forms </code><code>import</code> <code>ModelForm</code>

<code>from</code> <code>.models </code><code>import</code> <code>alionlineECS,alifuncECS,ksonlineECS,ksfuncECS,SLB,RDS</code>

<code>#定义ECS的Form,Form名字为 模式名+Form</code>

<code>class</code> <code>alionlineForm(ModelForm):</code>

<code>    </code><code>#自定义ModelForm的内容</code>

<code>    </code><code>class</code> <code>Meta:</code>

<code>        </code><code>#该ModelForm参照Model: ECS</code>

<code>        </code><code>model </code><code>=</code> <code>alionlineECS</code>

<code>        </code><code>#在Form中不显示node_signer这个字段  </code>

<code>        </code><code>exclude </code><code>=</code> <code>[</code><code>'ecs_signer'</code><code>]</code>

<code>        </code> 

<code>class</code> <code>alifuncForm(ModelForm):</code>

<code>        </code><code>model </code><code>=</code> <code>alifuncECS</code>

<code>class</code> <code>ksonlineForm(ModelForm):</code>

<code>        </code><code>model </code><code>=</code> <code>ksonlineECS</code>

<code>class</code> <code>ksfuncForm(ModelForm):</code>

<code>        </code><code>model </code><code>=</code> <code>ksfuncECS</code>

<code>class</code> <code>SLBForm(ModelForm):</code>

<code>        </code><code>model </code><code>=</code> <code>SLB</code>

<code>        </code><code>exclude </code><code>=</code> <code>[</code><code>'slb_signer'</code><code>]</code>

<code>class</code> <code>RDSForm(ModelForm):</code>

<code>        </code><code>model </code><code>=</code> <code>RDS</code>

<code>        </code><code>exclude </code><code>=</code> <code>[</code><code>'rds_signer'</code><code>]</code>

然后把urls.py进行一下整顿:

<code>from</code> <code>django.conf.urls </code><code>import</code> <code>url</code>

<code>from</code> <code>django.contrib </code><code>import</code> <code>admin</code>

<code>import</code> <code>Online.views</code>

<code>urlpatterns </code><code>=</code> <code>[</code>

<code>    </code><code>url(r</code><code>'^admin/'</code><code>,admin.site.urls),</code>

<code>    </code><code>url(r</code><code>'^lists/(?P&lt;table&gt;\w+)/$'</code><code>,Online.views.lists,name</code><code>=</code><code>'lists'</code><code>),</code>

<code>    </code><code>url(r</code><code>'^add/(?P&lt;table&gt;\w+)/$'</code><code>,Online.views.add,name</code><code>=</code><code>'add'</code><code>),</code>

<code>]</code>

最麻烦的地方就是views.py,这个变动比较大了:

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

<code># -*- coding: UTF-8 -*-</code>

<code>from</code> <code>django.shortcuts </code><code>import</code> <code>render,redirect</code>

<code>from</code> <code>forms </code><code>import</code> <code>alionlineForm,alifuncForm,ksonlineForm,ksfuncForm,SLBForm,RDSForm</code>

<code>def</code> <code>lists(request,table):</code>

<code>        </code><code>#不同的需求跳到不同的界面</code>

<code>        </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'alionlineECS'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>alionlineECS.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'alionlineECS_list.html'</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'alifuncECS'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>alifuncECS.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'alifuncECS_list.html'</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'ksonlineECS'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>ksonlineECS.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'ksonlineECS_list.html'</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'ksfuncECS'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>ksfuncECS.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'ksfuncECS_list.html'</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'SLB'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>SLB.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'slb_list.html'</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'RDS'</code><code>:</code>

<code>        </code><code>data </code><code>=</code> <code>RDS.objects.</code><code>all</code><code>()</code>

<code>        </code><code>list_template </code><code>=</code> <code>'rds_list.html'</code>

<code>        </code><code>#建立一个context,将值传递到对应的页面</code>

<code>    </code><code>context </code><code>=</code> <code>{</code>

<code>        </code><code>'data'</code><code>:data,</code>

<code>    </code><code>}</code>

<code>        </code><code>#跳转到相应页面,并将具体的值传递过去</code>

<code>    </code><code>return</code> <code>render(request,list_template,context)</code>

<code>def</code> <code>add(request,table):</code>

<code>    </code><code>#根据提交的请求不同,获取来自不同Form的表单数据</code>

<code>    </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'alionlineECS'</code><code>:</code>

<code>        </code><code>form </code><code>=</code>  <code>alionlineForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>        </code><code>form </code><code>=</code>  <code>alifuncForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>        </code><code>form </code><code>=</code>  <code>ksonlineForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>        </code><code>form </code><code>=</code>  <code>ksfuncForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>        </code><code>form </code><code>=</code>  <code>SLBForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>        </code><code>form </code><code>=</code>  <code>RDSForm(request.POST </code><code>or</code> <code>None</code><code>)</code>

<code>    </code><code>#判断form是否有效</code>

<code>    </code><code>if</code> <code>form.is_valid():</code>

<code>        </code><code>#创建实例,需要做些数据处理,暂不做保存</code>

<code>        </code><code>instance </code><code>=</code> <code>form.save(commit</code><code>=</code><code>False</code><code>)</code>

<code>        </code><code>#将登录用户作为登记人</code>

<code>                </code><code>instance.ecs_signer </code><code>=</code> <code>request.user</code>

<code>            </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'alifuncECS'</code><code>:</code>

<code>            </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'ksonlineECS'</code><code>:</code>

<code>            </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'ksfuncECS'</code><code>:</code>

<code>            </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'SLB'</code><code>:</code>

<code>                </code><code>instance.slb_signer </code><code>=</code> <code>request.user</code>

<code>            </code><code>if</code> <code>table </code><code>=</code><code>=</code> <code>'RDS'</code><code>:</code>

<code>                </code><code>instance.rds_signer </code><code>=</code> <code>request.user</code>

<code>        </code><code>#保存该实例</code>

<code>        </code><code>instance.save()</code>

<code>        </code><code>#跳转至列表页面  </code>

<code>        </code><code>return</code> <code>redirect(</code><code>'lists'</code><code>,table</code><code>=</code><code>table)</code>

<code>    </code><code>#创建context来集中处理需要传递到页面的数据 </code>

<code>        </code><code>'form'</code><code>: form,</code>

<code>    </code><code>#如果没有有效提交,则仍留在原来页面  </code>

<code>    </code><code>return</code> <code>render(request, </code><code>'add.html'</code><code>,context)</code>

上面我们写了很多个html,那么现在就要一个一个的补全这些html,比如alionlineECS_list.html,这里放上我们需要对外展示的节点,注意要跟model.py的各项一一对应:

<code>    </code><code>&lt;</code><code>meta</code> <code>charset</code><code>=</code><code>"UTF-8"</code><code>&gt;  </code>

<code>    </code><code>&lt;</code><code>title</code><code>&gt;&lt;/</code><code>title</code><code>&gt;  </code>

<code>&lt;/</code><code>head</code><code>&gt;</code>

<code>&lt;</code><code>body</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>table</code><code>&gt;</code>

<code>        </code><code>&lt;</code><code>tr</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器名称&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器类型&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器内网地址&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器外网地址&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器外网带宽&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;云服务器配置&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;备注&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;登记人&lt;/</code><code>th</code><code>&gt;</code>

<code>        </code><code>&lt;/</code><code>tr</code><code>&gt;</code>

<code>        </code><code>{% for item in data %}</code>

<code>            </code><code>&lt;</code><code>tr</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_name }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_type }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_inip }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_outip }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_ipwidth }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_spec }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_remarks }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.ecs_signer }}&lt;/</code><code>td</code><code>&gt;</code>

<code>            </code><code>&lt;/</code><code>tr</code><code>&gt;</code>

<code>        </code><code>{% endfor %}</code>

<code>    </code><code>&lt;/</code><code>table</code><code>&gt;</code>

<code>&lt;/</code><code>body</code><code>&gt;</code>

<code>&lt;/</code><code>html</code><code>&gt;</code>

而SLB.html就长这个样子:

<code>&lt;!DOCTYPE html&gt;</code>

<code>&lt;</code><code>html</code><code>&gt;</code>

<code>&lt;</code><code>head</code> <code>lang</code><code>=</code><code>"en"</code><code>&gt;  </code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;负载均衡名称&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;网络类型&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;转发规则&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;ip地址&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;负载均衡协议&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;前端端口&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;后端端口&lt;/</code><code>th</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_name }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_type }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_algorithm }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_ip }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_protocol }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_fport }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_bport }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_protocol2 }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_fport2 }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_bport2 }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_signer }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.slb_remarks }}&lt;/</code><code>td</code><code>&gt;</code>

RDS.html写成这个样子:

<code>            </code><code>&lt;</code><code>th</code><code>&gt;数据库名称&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;数据库类型&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;mysql版本&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;数据库规格&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;数据库地址&lt;/</code><code>th</code><code>&gt;</code>

<code>            </code><code>&lt;</code><code>th</code><code>&gt;存储空间&lt;/</code><code>th</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_name }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_type }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_mysql }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_spec }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_remark }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_ip }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_status }}&lt;/</code><code>td</code><code>&gt;</code>

<code>                </code><code>&lt;</code><code>td</code><code>&gt;{{ item.rds_signer }}&lt;/</code><code>td</code><code>&gt;</code>

这个时候我们启动django来到浏览器里,在地址栏输入:外网地址:8000/lists/alionlinecs,就会看到之前的那个添加“阿里云线上服务器”的界面,如图:

在点击了提交之后,就会看到地址栏里的add变成了lists,达到了我们的预期目标:

1.      Django处理请求的方式

1) Django通过URLconf模块来进行判断。通常情况下,这就是ROOT_URLCONF配置的价值,但是如果请求携带了一个urlconf的属性(通常被中间件设置),那么这个被携带的urlconf将会替代ROOT_URLCONF的配置。

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&lt;name&gt;pattern), name 可以理解为所要传递的参数的名称,pattern代表所要匹配的模式。例如,

url(r'^articles/(?P&lt;year&gt;[0-9]{4})/(?P&lt;month&gt;[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()方法

 本文转自 苏幕遮618 51CTO博客,原文链接:http://blog.51cto.com/chenx1242/1948971