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代表所要匹配的模式。例如,

  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()方法
时间: 2024-08-24 03:38:46

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

Django运维后台的搭建之一:使用model建立数据信息

2017年的上半年对我来说是极其难忘的一年,整个乐橙运营部的平台运维全靠我一个人,而且同时公司又新上了一个阿里深圳区一个杭州公有云两套环境外加一套演示环境.所以一直念叨的运维后台始终拖拖拉拉,现在公司又招来一个小弟给我打下手,我终于有时间去把这个小心愿完成,于是就有了这一系列文章,主要是给自己一个记录也是为了方便后来人. 首先,先说一下我的环境,本人使用阿里云centos7.0,django的版本是1.10.3,python是2.7,django目录就是/django. 首先在/django里#

Django运维后台的搭建之五:引入databases和django-crispy-forms

在上一篇,我们已经把我们做的运维外面套上了bootstrap框架,但是那仅仅是一个外壳,这一次是要把里面的壤也扣上这样的框架. 首先,编辑index.html,添加block元素,用于主页存放不同的内容: <div class="page-content">      <div class="page-content-area">                       <div class="page-header&qu

Django运维后台的搭建之四:用bootstrap模板让运维前台变得更漂亮

我对于PHP和ajax是属于二把刀的水平,所以做网页前端肯定是比上天还难,但是我又想把网页做的漂亮可爱,怎么办呢?我就只好去download别人的模板,在这里我使用了bootstrap框架做的模板. 各位可以去https://wrapbootstrap.com  ,里面有很多漂亮的模板提供下载,当然是付费下载.我在这片文章里使用的是https://wrapbootstrap.com/theme/ace-responsive-admin-template-WB0B30DGR  这个. 首先把这个a

Linux运维学习之 —— 搭建本地yum源

yum是RPM的前端工具,通过yum命令可以帮我们自动解决安装rpm包之间的依赖关系.下面是搭建本地yum仓库的步骤: 1.挂载光盘(光盘为CentOS-6.5-x86_64-bin-DVD2.iso)     mount /dev/cdrom1 /media ls一下/media这个目录,可以看到以下内容 2.创建本地文件夹,将Packages下的rpm包全部拷贝到本地文件夹     mount /dev/cdrom1 /media/     cp -r /media/Packages/* /

网络运维与网络安全介绍之三

通过2019-12-07的博客(网络运维与网络安全介绍之二的补),到目前为止,我们手里头有两个资源,第一个就是:windows10映像文件(.iso,4.3GB左右),第二个就是:一个内存至少是8GB的移动U盘.接下来,就是做启动U盘了,那为啥做启动U盘呢,在2000年时代的时候,我们的大哥大姐们装系统都是拿系统光盘来装的,现在没有系统光盘了(为了环保,为了资源),那该怎么装系统呢?就得借助于启动U盘了,由于我在另外一个平台发布了制作启动U盘的详细过程,请大家直接查看网络运维与网络安全介绍之三.

运维实战案例之文件已删除但空间不释放问题解析

1.错误现象 运维的监控系统发来通知,报告一台服务器空间满了,登陆服务器查看,根分区确实没有空间了,如下图所示: 这里首先说明一下服务器的一些删除策略,由于Linux没有回收站功能,我们的线上服务器所有要删除的文件都会首先移动到系统/tmp目录下,然后定期清除/tmp目录下的数据.这个策略本身没有问题,但是通过检查发现这台服务器的系统分区中并没有单独划分/tmp分区,这样/tmp下的数据其实是占用了根分区的空间.既然找到了问题,那么删除/tmp目录下一些大数据即可,执行如下命令,检查/tmp下最

【手游自动化运维后台】-简示-可二次开发

架构: python+Django 适用:手游自动化运维操作... 登录模块 登录主界面及菜单功能: 功能模块示例: 权限模块示例: 日志模块: 不同架构不一定都试用,可评估是否能二次开发

django 运维工单系统

此工单系统从立项到完成,大概用了1个星期,可能部分思路和实现有所不妥,欢迎指正. 朋友公司想做一个运维工单系统,他没思路,正好我最近打算写一个运维工单系统,初步打算和我目前做的cmdb系统结合起来,于是简单写了个. 简单说下实现思路: 1.标准工单,(参考上家公司的工单系统,对工单做了分类,且每个分类下有对应的审批人和执行人) 2.新建工单(用户从上边的标准工单可以进入对应的工单申请,分为保存和提交两种状态,用户提交后将无法在修改,暂缺一个时间控件,任务类型默认为点击进入的类型,但允许用户进行修

Django中模板总结[模板语言,模板继承,CSRF攻击,反向解析]

模板 概述 作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器.模版致力于表达外观,而不是程序逻辑.模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用. 创建模板文件夹 在项目的文件里面定义一个templates文件夹 在创建的文件夹里面再创建一个文件夹为每个应用的html文件夹 起名为和应用名同名的文