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

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介:

上一篇文章里,我们做了一个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,就会看到之前的那个添加“阿里云线上服务器”的界面,如图:

wKiom1lvEyzQlngVAAC0aSkWyiY066.png


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

wKiom1lvE6WT5s87AADMT6LNsoA671.png



在这篇文章的最后,我直接复制了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代表所要匹配的模式。例如,

  1. 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的反向解析。反向解析的例子,

  1. 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
相关文章
|
2月前
|
存储 缓存 前端开发
Django 后端架构开发:存储层调优策略解析
Django 后端架构开发:存储层调优策略解析
40 2
|
2月前
|
缓存 运维 监控
打造稳定高效的数据引擎:数据库服务器运维最佳实践全解析
打造稳定高效的数据引擎:数据库服务器运维最佳实践全解析
|
2月前
|
缓存 运维 Linux
深入解析:一步步掌握 CentOS 7 安装全流程及运维实战技巧
深入解析:一步步掌握 CentOS 7 安装全流程及运维实战技巧
|
2月前
|
数据采集 运维 监控
运维笔记:流编辑器sed命令用法解析
运维笔记:流编辑器sed命令用法解析
45 5
|
2月前
|
存储 API 数据库
Django后端架构开发:构建在线云媒资系统思路解析
Django后端架构开发:构建在线云媒资系统思路解析
38 0
|
2月前
|
运维 Rust 监控
Linux高效运维必备:fd命令深度解析,文件描述符管理从此得心应手!
【8月更文挑战第23天】本文介绍了一款名为fd的命令行工具,该工具基于Rust语言开发,旨在以更直观的语法和更快的速度替代传统的`find`命令。通过本文,您可以了解到如何安装fd以及一些基本用法示例,比如使用正则表达式匹配文件名、排除特定目录等。此外,文章还展示了如何结合`ps`和`lsof`命令来查找特定文件并显示其文件描述符,从而帮助您更好地管理和监控Linux系统中的文件与进程。
79 0
|
2月前
|
存储 运维 监控
运维.Linux下执行定时任务(上:Cron简介与用法解析)
运维.Linux下执行定时任务(上:Cron简介与用法解析)
39 0
|
2月前
|
运维 关系型数据库 MySQL
"MySQL运维精髓:深入解析数据库及表的高效创建、管理、优化与备份恢复策略"
【8月更文挑战第9天】MySQL是最流行的开源数据库之一,其运维对数据安全与性能至关重要。本文通过最佳实践介绍数据库及表的创建、管理与优化,包括示例代码。涵盖创建/删除数据库、表结构定义/调整、索引优化和查询分析,以及数据备份与恢复等关键操作,助您高效管理MySQL,确保数据完整性和系统稳定运行。
151 0
|
4月前
|
前端开发 数据库 开发者
构建高效后端:Django框架在Web开发中的深度解析
**Django框架深度解析摘要** Django,Python的高级Web框架,以其快速开发和简洁设计备受青睐。核心特性包括Model-Template-View架构、ORM、模板引擎和URL路由。通过创建博客应用示例,展示从初始化项目、定义模型、创建视图和URL配置到使用模板的流程,体现Django如何简化开发,提高效率。其强大功能如用户认证、表单处理等,使Django成为复杂Web应用开发的首选。学习Django,提升Web开发效率。【6月更文挑战第24天】
79 1
|
4月前
|
前端开发 JavaScript 安全
跨域问题与Django解决方案:深入解析跨域原理、请求处理与CSRF防护
跨域问题与Django解决方案:深入解析跨域原理、请求处理与CSRF防护

推荐镜像

更多
下一篇
无影云桌面