Django运维后台的搭建之三:用url去精细定制与反向解析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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:
# -*- 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进行一下整顿:
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,这个变动比较大了:
# -*- 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的各项一一对应:
<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就长这个样子:
<!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写成这个样子:
<!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()方法
本文出自 “生活就是等待戈多” 博客,请务必保留此出处http://chenx1242.blog.51cto.com/10430133/1948971
以上是关于Django运维后台的搭建之三:用url去精细定制与反向解析的主要内容,如果未能解决你的问题,请参考以下文章
1-3.Win10系统利用Pycharm社区版安装Django搭建一个简单Python Web项目的步骤之三