django 反向路由怎么用一个路由

django开发电子商城(二十一)结算的登录验证和路由跳转 - 简书
django开发电子商城(二十一)结算的登录验证和路由跳转
1:在views.py中创建结算的响应函数
2:在urls.py中,增加结算页面的路由
3:给“去结算”按钮增加点击功能
点击去结算按钮,运行结果如下:
4:导入登录验证库,并用来修饰oder_computer函数
5:在settings.py中设置登录路由的URL
6:对view.py中的index_login登录函数进行修改,如果登录成功且存在next的情况下,跳转到next;如果登录成功但不存在next的情况下,跳转到首页7:修改login .html前端页面,登录表单地址改为request.get_full_path,方便后台从地址中用get方法取到next的地址8:修改shop_cart.html,利用URL地址,将购物车商品的ID传输到后台9:修改views.py中的order_computer,从URL地址中获取商品ID列表10:运行结果如下:
本来做了个目录快速跳转的,后来简书不再支持这种写法,无奈阅读只能自己根据章节明ctrl+f/v/enter来定位了 ┑( ̄Д  ̄)┍ --------------------------目录结构----------------------- 前言 Flask框架的特点 本书...
此段内容简要来自自强学堂的教程详情请查询自强学堂 一、 后台的运作流程 接收request请求 处理数据 获取请求数据 访问数据库 生成返回数据 返回response回复 二、 安装django 前期要求 windows8.1系统 python 2.7.12 pip 8.1...
经过对django的初步学习,我们已经对后台的基本流程以及django的运作有了一定的了解,但是这还不足够,django还有许多方法和API需要我们详细滴学习,是时候开始进阶学习了。上期文章:后台学习——django(1) 零、上篇文章修改 静态文件引用修改 在上篇文章就说...
已经同步到gitbook,想阅读的请转到gitbook: Django 1.10 中文文档 URL dispatcher? A clean, elegant URL scheme is an important detail in a high-quality Web ap...
4 创建一个社交网站 在上一章中,你学习了如何创建站点地图和订阅,并且为博客应用构建了一个搜索引擎。在这一章中,你会开发一个社交应用。你会为用户创建登录,登出,编辑和修改密码的功能。你会学习如何为用户创建自定义的个人资料,并在网站中添加社交认证。 本章会涉及以下知识点: 使...
多年来,每年元旦,我都会读一下南方周末的这篇文章《阳光打在你脸上》,每次读完,都有一种拷问,都有一种温暖,都有一种力量。
谨以此文祝大家新年好!
1999年《南方周末》新年贺词 这是新年的第一天。这是我们与你见面的第777次。祝愿阳光打在你的脸...
题记:如果惧怕黑夜,就努力成为黑夜;如果胆颤幽灵,就设法与幽灵同眠。 好了,开始这篇欠了一天的流水。为方便叙述,我还是用现在时吧。 霭霭晨色,在施洞此消彼长的鸡鸣声中,我醒了。今天计划去施秉云台山,昨晚跟老板打听好去施秉的班车信息:一天仅两班,上午的是8:00钟过河对面的马...
思考不要用蛮力,工作不只靠劳力。 工时长短根本不是重点,重点在于只要交出有价值的输出就好。 知识的增长不一定会带动智慧的增长反而必须经常去有一个观念信息量在超过某个程度之后将会造成负面效果 实验有两种结果,倘若结果验证了假说,就表示你测得什么,倘若结果推翻了假说,就表示你发...
有人告诉小编《红楼梦》是一部非常优秀的职场教科书。于是笔者又去买了一本经典版红楼梦细细品读,自从初中阅过之后,就再无交集,没想到现在拿起,已是觉得原来是满书的学问和经纶。 红楼梦中蕴含了富的职场哲学,特别值得我们这些已经走上工作岗位的人和那些即将走上工作岗位的学生借鉴与学习...1、单一路由对应
&<span style="color: # url(r'^index$', views.index),&
2、基于正则的路由
<span style="color: # url(r'^index/(\d*)', views.index),
<span style="color: # url(r'^manage/(?P&name&\w*)/(?P&id&\d*)', views.manage),
3、添加额外的参数,默认的参数
&<span style="color: # url(r'^manage/(?P&name&\w*)', views.manage,{'id':333}),&
4、为路由映射设置名称
<span style="color: # url(r'^home', views.home, name='h1'),
<span style="color: # url(r'^index/(\d*)', views.index, name='h2'),
5、根据app对路由规则进行分类
&<span style="color: # url(r'^web/',include('web.urls')),&
1 urlpatterns = [
url(r'^admin/', admin.site.urls),
#url----function
url(r'^index/',index ),
url(r'^Login/',login ),
#配置动态的URL,因为此时不确定我会产生多少条url,此时在函数中需要加上一个捕获的参数,id,用来捕获用户的id
#尖括号里面的值需要与业务逻辑层次上对应,模板格式
<span style="color: #
url(r'^list/(?P&name&\d*)/(?P&id&\d*)/',list ),
<span style="color: #
#设置默认值
<span style="color: #
url(r'^list/(?P&name&\d*)/',list ,{'id':222}),
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # ]
分类的url:
1 urlpatterns = [
url(r'^admin/', admin.site.urls),
#url----file
#file-----url&function 类似于路径映射,本来是单纯的由jango里面的urls(全局的url)统一的配置路由信息,但是如果我的app多了之后这就会显得有点乱,所以此时可以指定URL路径,由各自的APP去执行url,每个路径多加了一个分类的路径
url(r'^ad/', include('ad.urls')),
<span style="color: #
url(r'^web/',include('web.urls')),
<span style="color: #
<span style="color: # ]
6、通过反射机制,为django开发一套动态的路由系统
在urls.py里定义分类正则表达式
1 from django.conf.urls import patterns, include, url
2 from django.contrib import admin
3 from DynamicRouter.activator import process
5 urlpatterns = patterns('',
# Examples:
# url(r'^$', 'DynamicRouter.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
<span style="color: #
url(r'^admin/', include(admin.site.urls)),
<span style="color: #
<span style="color: #
<span style="color: #
('^(?P&app&(\w+))/(?P&function&(\w+))/(?P&page&(\d+))/(?P&id&(\d+))/$',process),
<span style="color: #
('^(?P&app&(\w+))/(?P&function&(\w+))/(?P&id&(\d+))/$',process),
<span style="color: #
('^(?P&app&(\w+))/(?P&function&(\w+))/$',process),
<span style="color: #
('^(?P&app&(\w+))/$',process,{'function':'index'}),
<span style="color: # )
在同目录下创建activater.py
1 #!/usr/bin/env python
2 #coding:utf-8
4 from django.shortcuts import render_to_response,HttpResponse,redirect
7 def process(request,**kwargs):
'''接收所有匹配url的请求,根据请求url中的参数,通过反射动态指定view中的方法'''
<span style="color: #
kwargs.get('app',None)
<span style="color: #
function = kwargs.get('function',None)
<span style="color: #
<span style="color: #
<span style="color: #
appObj = __import__("%s.views" %app)
<span style="color: #
viewObj = getattr(appObj, 'views')
<span style="color: #
funcObj = getattr(viewObj, function)
<span style="color: #
<span style="color: #
#执行view.py中的函数,并获取其返回值
<span style="color: #
result = funcObj(request,kwargs)
<span style="color: #
<span style="color: #
except (ImportError,AttributeError),e:
<span style="color: #
#导入失败时,自定义404错误
<span style="color: #
return HttpResponse('<span style="color: #4 Not Found')
<span style="color: #
except Exception,e:
<span style="color: #
#代码执行异常时,自动跳转到指定页面
<span style="color: #
return redirect('/app01/index/')
<span style="color: #
<span style="color: #
return result
阅读(...) 评论()django学习笔记3:视图与路由
3:Django视图与路由
首先新建一个项目
django-admin startproject mytest
项目生成后的目录结构
|----manage.py
|----mytest
|----__init__.py
|----settings.py
|----urls.py
|----wsgi.py
新建app应用:
到 mytest 目录下生成app
django-admin startapp test1(app名称)
目录结构:
|----manage.py
|----mytest
|----__init__.py
|----settings.py
|----urls.py
|----wsgi.py
|----test1
|----__init__.py
|----admin.py
|----apps.py
|----models.py
|----tests.py
|----views.py
|----migrations
|----__init__.py
在settings.py 的
INSTALLED_APPS 中添加 app
修改mytest\mytest下的settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]备注,这一步是干什么呢? 新建的 app 如果不加到 INSTALL_APPS 中的话, django 就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)
定义视图函数:
修改 mytest\test1\views.py
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("hello world 你好")第一行是声明编码为utf-8, 因为我们在代码中用到了中文,如果不声明就报错.
第二行生成views.py时就有
第三行引入HttpResponse,它是用来向网页返回内容的,就像Python中的 print 一样,只不过 HttpResponse 是把内容显示到网页上。
我们定义了一个index()函数,第一个参数必须是 request,与网页发来的请求有关,request 变量里面包含get或post的内容,用户浏览器,系统等信息在里面。
函数返回了一个 HttpResponse 对象,可以经过一些处理,最终显示几个字到网页上。
定义视图函数相关的URL
修改mytest\test1\url.py
from django.conf.urls import url
from django.contrib import admin
from test1 import views as test1_views
urlpatterns = [
url(r'^$',test1_views.index),
url(r'^admin/', admin.site.urls),
]先引入app的视图,再定义视图的URL
视图和URL进阶
修改mytest\test1\views.py
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("hello world 你好")
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a)+int(b)
return HttpResponse(str(c))添加一个add视图函数,get两个参数,回传页面参数之和
修改mytest\test1\url.py
from django.conf.urls import url
from django.contrib import admin
from test1 import views as test1_views
urlpatterns = [
url(r'^$',test1_views.index),
url(r'^admin/', admin.site.urls),
url(r'^add/$',test1_views.add,name='add'),
]启动服务打开浏览器127.0.0.1:8000/add/会发现报错,找不到参数a这是因为没有传入参数,访问127.0.0.1:8000/add/?a=123&b=456页面就显示出参数相加的和了采用/add/4/5这样的URL形式
修改mytest\test1\views.py
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse("hello world 你好")
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a)+int(b)
return HttpResponse(str(c))
def add2(request,a,b):
c=int(a)+int(b)
return HttpResponse(str(c))修改mytest\test1\url.py
from django.conf.urls import url
from django.contrib import admin
from test1 import views as test1_views
urlpatterns = [
url(r'^$',test1_views.index),
url(r'^admin/', admin.site.urls),
url(r'^add/$',test1_views.add,name='add'),
url(r'^add/(\d+)/(\d+)/$',test1_views.add2,name='add2') ,
]起服务,输入URL,127.0.0.1:8000/add/1/3页面显示了参数相加
URL中的name
url(r'^add/$', calc_views.add, name='add'),
如果在url.py中修改一个url的正则表达式,如果静态页面文件中是写死的&a href="/add2/4/5/"&计算 4+5&/a&,那网页跳转会出问题
灵活的方式是不要写死url,如下
不带参数的:
{% url 'name' %}
带参数的:参数可以是变量名
{% url 'name' 参数 %}
&a href="{% url 'add2' 4 5 %}"&link&/a&
这时候改变url的正则表达式,但是不变后面的name值
url(r'^new_add/(\d+)/(\d+)/$', 'calc.views.add2', name='add2'),
页面的add2会被渲染成new_add
如果想让原来的url都能自动跳转到新的url,也就是重定向,需要修改一下views.py和url.py
修改mytest\test1\views.py
#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect
from django.core.urlresolvers import reverse
def index(request):
return HttpResponse("hello world 你好")
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a)+int(b)
return HttpResponse(str(c))
def add2(request, a, b):
c = int(a) + int(b)
return HttpResponse(str(c))
def old_add2(request,a,b):
return HttpResponseRedirect(
reverse('add2',args=(a,b))
HttpResponseRedirect是重定向
reverse('add2',args=(a,b) ) 是获取一个/add2/a/b/形式的url
修改mytest\test1\url.py
from django.conf.urls import url
from django.contrib import admin
from test1 import views as test1_views
urlpatterns = [
url(r'^$',test1_views.index),
url(r'^admin/', admin.site.urls),
url(r'^add/$',test1_views.add,name='add'),
url(r'^add2/(\d+)/(\d+)/$', test1_views.old_add2),
url(r'^new_add2/(\d+)/(\d+)/$',test1_views.add2,name='add2')
将原来的add2/a/b/形式url指向重定向视图
将新的new_add2/a/b/形式指向原来的add2视图函数
这样在浏览器中输入127.0.0.1:8000/add2/1/3/会自动跳转到127.0.0.1:8000/new_add2/1/3/
没有更多推荐了,django搭建一个小型的服务器运维网站-查看和修改服务器配置与数据库的路由
查看和修改服务器配置与数据库的路由;
基于websocket的实时日志实现;
查看服务器中的日志与前端的datatable的利用;
重启服务器某个进程;
申请云服务器并进行正式配置。
运维过程中,常常希望修改一些配置文件,文章用网站的功能替代登陆服务器修改文件,并不是十全十美,总得来说,实现了功能。文章主要分为两个部分,分别是数据库的路由和服务器配置的处理。这个功能页面如图1所示。
数据库的路由
一个django项目通常会有多个app,一般每个app的功能差异较大,造成models.py差异也较大,可以为每一个app设置一个单独的存储数据库。这个项目中server就有一个单独的数据库存储它有的一些表(图2 蓝框),其他的功能默认存储在mysql这个默认的数据库中(图2 红框)。要使用该功能需要修改项目的配置(settings.py)文件。
修改settings
# Database 配置
DATABASE_ROUTERS = [&#x27;WebTool.database_router.DatabaseAppsRouter&#x27;]
DATABASE_APPS_MAPPING = {
# example:
# &#x27;app_name&#x27;:&#x27;database_name&#x27;,
# 为server单独设置一个名字叫做server的数据库
&#x27;server&#x27;: &#x27;server&#x27;,
DATABASES = {
# 默认的数据库,未指定存放位置的表会建在这个数据库里面,也包含一些django自带的表
&#x27;default&#x27;: {
&#x27;ENGINE&#x27;: &#x27;django.db.backends.mysql&#x27;,
&#x27;NAME&#x27;: &#x27;mysql&#x27;,
&#x27;USER&#x27;: &#x27;root&#x27;,
&#x27;PASSWORD&#x27;: &#x27;root&#x27;,
&#x27;HOST&#x27;: &#x27;127.0.0.1&#x27;,
&#x27;PORT&#x27;: &#x27;&#x27;,
# server的数据库
&#x27;server&#x27;: {
&#x27;ENGINE&#x27;: &#x27;django.db.backends.mysql&#x27;,
&#x27;NAME&#x27;: &#x27;server&#x27;,
&#x27;USER&#x27;: &#x27;root&#x27;,
&#x27;PASSWORD&#x27;: &#x27;root&#x27;,
&#x27;HOST&#x27;: &#x27;127.0.0.1&#x27;,
&#x27;PORT&#x27;: &#x27;&#x27;,
添加database_router.py文件
在WebTool/WebTool下添加一个py文件用来实现数据库路由功能,文件命名为database_router.py,如图3红框位置。
from django.conf import settings
DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
class DatabaseAppsRouter(object):
A router to control all database operations on models for different
databases.
In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
will fallback to the &#96;default&#96; database.
Settings example:
DATABASE_APPS_MAPPING = {&#x27;app1&#x27;: &#x27;db1&#x27;, &#x27;app2&#x27;: &#x27;db2&#x27;}
def db_for_read(self, model, **hints):
&&&&Point all read operations to the specific database.&&&
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
&&&Point all write operations to the specific database.&&&
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def allow_relation(self, obj1, obj2, **hints):
&&&Allow any relation between apps that use the same database.&&&
db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
return False
return None
def allow_syncdb(self, db, model):
&&&Make sure that apps only appear in the related database.&&&
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(model._meta.app_label) == db
elif model._meta.app_label in DATABASE_MAPPING:
return False
return None
def allow_migrate(self, db, app_label, model=None, **hints):
Make sure the auth app only appears in the &#x27;auth_db&#x27;
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(app_label) == db
elif app_label in DATABASE_MAPPING:
return False
return None
在model函数中建立映射
前篇文章中曾经设置过两个model函数分别是taskinbackground和modifytime,app_label就是用来区分该函数用来对应哪个数据库的,app_label = &server&是把表建立在server这个数据库里面。
class taskinbackground(models.Model):
taskname = models.CharField(max_length=50)
taskor = models.CharField(max_length=100)
class Meta:
db_table = &#x27;task&#x27;
app_label = &server&
class modifytime(models.Model):
modifyer = models.CharField(max_length=100)
modifytime = models.CharField(max_length=200, default=&&)
modifyservertime = models.CharField(max_length=200, default=&&)
class Meta:
db_table = &#x27;modifytime&#x27;
app_label = &server&
初始化数据库
执行python manage.py makemigrations、python manage.py migrate、python manage.py migrate --database=server三条指令分别用来更新数据库、刷新默认的数据库和server的数据库。这样,一个数据库的路由就可以了,现在可以不同app对应不同的数据库了。
服务器配置
这个页面功能可以用下图4概括,其中的函数来自于中。实现这个些功能中会遇到一些小细节的处理。
这里直接给出页面的html代码:
{% extends &.&#x2F;base.html& %}
{% block othercss %}{% endblock %}
{% block title %}{{ title }}{% endblock %}
{% block log %}{{ title }}{% endblock %}
{% block username %}{{ username }}{% endblock %}
{% block mainbody %}
&section class=&wrapper site-min-height&&
&h3&&i class=&fa fa-angle-right&&&&#x2F;i& 服务器配置 &i class=&fa fa-cog&&&&#x2F;i&&&#x2F;h3&
&div class=&row mt&&
&div class=&form-panel&&
&div class=&col-lg-12 row mt&&
&div class=&col-sm-6&&
&h4 class=&mb& style=&float:dispaly:&&服务器配置&&#x2F;h4&
&button type=&button& class=&btn btn-theme02& id=&#x27;getconfig&#x27; style=&float:dispaly:&&更新服务器配置&&#x2F;button&
&&#x2F;div&
&div class=&col-sm-6&&
&div class=&col-sm-12&&
&!--onkeyup=&searchintable()& 当每次输入键盘弹起后就调用函数--&
&input type=&text& class=&form-control& onkeyup=&searchintable()& id=&search& placeholder=&配置搜索&&
&&#x2F;div&
&&#x2F;div&
&div class=&col-sm-12&&
&!-- 获取配置的时候出现的加载图标 --&
&div class=&progress progress-striped active& style=&display:none& id=&loading&&
&div class=&progress-bar& role=&progressbar& aria-valuenow=&100& aria-valuemin=&0& aria-valuemax=&100& style=&width: 100%&&&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&table class=&table table-striped table-advance table-hover& id=&configtable&&
&th style=&width:15%;&&&i class=&fa fa-cog&&&&#x2F;i& 配置文件&&#x2F;th&
&th style=&width:55%;& class=&hidden-phone&&&&&&&i class=&fa fa-question-circle&&&&#x2F;i& 配置描述&&#x2F;th&
&th&&i class=& fa fa-edit&&&&#x2F;i& 操作&&#x2F;th&
&&#x2F;tr&
&&#x2F;thead&
{% for index,name,detail in name_list %}
&td style=&vertical-align:&&{{ name }}&&#x2F;td&
{% if detail == &#x27;&#x27; %}
&td tyle=&vertical-align:&&
&div class=&col-sm-8&&
&div class=&input-group&&
&input type=&text& class=&form-control& placeholder=&#x27;此处可以添加配置描述&#x27;&
&span class=&input-group-btn&&
&button class=&btn btn-default& onclick=&write_detail(this, &{{name}}&)& type=&button&&添加&&#x2F;button&
&&#x2F;span&
&&#x2F;div&
&&#x2F;div&
&&#x2F;td&
{% else %}
&td style=&vertical-align:&&
&div class=&col-sm-8&&
&div class=&input-group& style=&display:&&
&input type=&text& class=&form-control& placeholder=&#x27;此处可以添加配置描述&#x27;&
&span class=&input-group-btn&&
&button class=&btn btn-default& onclick=&write_detail(this, &{{name}}&)& type=&button&&添加&&#x2F;button&
&&#x2F;span&
&&#x2F;div&
{{ detail }}&&&button onclick=&modify_detail(this)& style=&border:0;background:&&&i class=&fa fa-pencil&&&&#x2F;i&&&#x2F;button&
&&#x2F;div&
&&#x2F;div&
&&#x2F;td&
{% endif %}
&!-- 每一行配置的三个操作按钮 --&
&td style=&vertical-align:&&
&button class=&btn btn-success btn-sm& data-toggle=&modal& data-target=&#readModal& onclick=&readbutton(&{{name}}&)&&&i class=&fa fa-eye&&&&#x2F;i&&&#x2F;button&
&button class=&btn btn-primary btn-sm& data-toggle=&modal& data-target=&#writeModal& onclick=&writebutton(&{{name}}&)&&&i class=&fa fa-pencil&&&&#x2F;i&&&#x2F;button&
&button class=&btn btn-danger btn-sm& onclick=&deletebutton(&{{name}}&)&&&i class=&fa fa-trash-o&&&&#x2F;i&&&#x2F;button&
&&#x2F;td&
&&#x2F;tr&
{% endfor %}
&&#x2F;tbody&
&&#x2F;table&
&&#x2F;div&
&&#x2F;div&
&&#x2F;section&
&!-- 查看配置模态框 --&
&div class=&modal fade& id=&readModal& tabindex=&-1& role=&dialog& aria-labelledby=&myModalLabel& aria-hidden=&true&&
&div class=&modal-dialog&&
&input type=&hidden& name=&#x27;modal&#x27; value=&#x27;&#x27;&
&div class=&modal-content&&
&div class=&modal-header&&
&button type=&button& class=&close& data-dismiss=&modal& aria-hidden=&true&&
&&#x2F;button&
&h4 class=&modal-title& id=&myModalLabelread&&
模态框(Modal)标题
&&#x2F;h4&
&&#x2F;div&
&!--style=&cursor:default& 设置只读状态--&
&textarea type=&text& class=&form-control modal-body-read& rows=&35& placeholder=&& readonly=&readonly& style=&cursor:default&&
在这里添加一些文本
&&#x2F;textarea&
&div class=&modal-footer&&
&button type=&button& class=&btn btn-theme02& data-dismiss=&modal&&关闭
&&#x2F;button&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&!-- 修改配置模态框 --&
&div class=&modal fade& id=&writeModal& tabindex=&-1& role=&dialog& aria-labelledby=&myModalLabel& aria-hidden=&true&&
&div class=&modal-dialog&&
&input type=&hidden& id=&#x27;configname&#x27; name=&#x27;modal&#x27; value=&#x27;&#x27;&
&div class=&modal-content&&
&div class=&modal-header&&
&button type=&button& class=&close& id=&closebtn1& data-dismiss=&modal& aria-hidden=&true&&
&&#x2F;button&
&h4 class=&modal-title& id=&myModalLabelwrite&&
模态框(Modal)标题
&&#x2F;h4&
&&#x2F;div&
&div class=&progress progress-striped active& style=&display:& id=&writeloading&&
&div class=&progress-bar& role=&progressbar& aria-valuenow=&100& aria-valuemin=&0& aria-valuemax=&100& style=&width: 100%&&&&#x2F;div&
&&#x2F;div&
&textarea type=&text& class=&form-control modal-body-write& rows=&35& placeholder=&&&&&#x2F;textarea&
&div class=&modal-footer&&
&button type=&button& class=&btn btn-theme03& id=&putconfigbtn& onclick=&putconfig()&&提交&&#x2F;button&
&button type=&button& class=&btn btn-theme02& id=&closebtn2& data-dismiss=&modal&&关闭&&#x2F;button&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
{% endblock %}
页面使用到的javascript函数:
{% block scripts %}
&#x2F;&#x2F; 提交修改后的配置
function putconfig(){
title: &#x27;提交新的配置?&#x27;,
type: &#x27;warning&#x27;,
confirmButtonColor: &#x27;#DD6B55&#x27;,
confirmButtonText:&是的&,
cancelButtonText:&不用&,
showLoaderOnConfirm: true, &#x2F;&#x2F;加载按钮是否可见
showCancelButton: true,
preConfirm: function() {
return new Promise(function(resolve) {
setTimeout(function(){
$(&#putconfigbtn&).hide();
$(&#closebtn1&).hide();
$(&#closebtn2&).hide();
$(&#writeloading&).show();
resolve();
allowOutsideClick: false, &#x2F;&#x2F;弹框外是否可点
}).then(function(res){
url:&writeconfig&,
type:&#x27;POST&#x27;,
data:{&#x27;name&#x27;:$(&#configname&).val(), &#x27;content&#x27;:$(&.modal-body-write&).val()},
success: function(arg){
ret = eval(arg);
if(ret.status){
type: &#x27;success&#x27;,
title: &#x27;设置修改成功!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;,
allowOutsideClick: false,
}).then(function(){
window.location.reload();
if(ret.error == &#x27;1&#x27;){
type: &#x27;error&#x27;,
title: &#x27;json格式错误,请重新修改!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;,
allowOutsideClick: false,
}).then(function(){
window.location.reload();
type: &#x27;error&#x27;,
title: &#x27;设置修改失败!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;,
allowOutsideClick: false,
}).then(function(){
window.location.reload();
&#x2F;&#x2F; 只读按钮
function readbutton(configname){
$(&#myModalLabelread&).html(&&b&查看&+configname+&配置&&#x2F;b&&);
url:&readconfig&,
type:&#x27;POST&#x27;,
data:{&#x27;configname&#x27;:configname},
success: function(arg){
ret = eval(arg);
content = ret.
var json = JSON.parse(content);
$(&.modal-body-read&).html(JSON.stringify(json,null,4));
&#x2F;&#x2F; 修改按钮
function writebutton(configname){
$(&#myModalLabelwrite&).html(&&b&修改&+configname+&配置&&#x2F;b&&);
&#x2F;&#x2F; 模态框中添加一个属性用来记录配置的名字,方便提交配置取配置的名字
$(&#configname&).val(configname);
url:&readconfig&,
type:&#x27;POST&#x27;,
data:{&#x27;configname&#x27;:configname},
success: function(arg){
ret = eval(arg);
content = ret.
var json = JSON.parse(content);
&#x2F;&#x2F; JSON.stringify(json,null,4)函数可以将字符串格式化成json格式
$(&.modal-body-write&).html(JSON.stringify(json,null,4));
&#x2F;&#x2F; 删除配置
function deletebutton(configname){
title: &#x27;删除&#x27;+configname+&#x27;这个配置?&#x27;,
type: &#x27;warning&#x27;,
confirmButtonColor: &#x27;#DD6B55&#x27;,
confirmButtonText:&是的&,
cancelButtonText:&不用&,
showLoaderOnConfirm: true, &#x2F;&#x2F;加载按钮是否可见
showCancelButton: true,
preConfirm: function() {
return new Promise(function(resolve) {
setTimeout(function(){
resolve();
allowOutsideClick: false, &#x2F;&#x2F;弹框外是否可点
}).then(function(res){
url:&deleteconfig&,
type:&#x27;POST&#x27;,
data:{&#x27;name&#x27;:configname },
success: function(arg){
ret = eval(arg);
if(ret.status){
if(ret.status){
type: &#x27;success&#x27;,
title: &#x27;删除完成!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;
}).then(function(){
window.location.reload();
type: &#x27;error&#x27;,
title: &#x27;删除失败!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;
}).then(function(){
window.location.reload();
&#x2F;&#x2F; 为配置添加描述
function write_detail(obj, name){
var father_span = obj.parentN
var input = $(father_span).prev();
var detail = input.val();
url:&configdetail&,
type:&#x27;POST&#x27;,
data:{&#x27;name&#x27;:name, &#x27;detail&#x27;:detail},
success: function(arg){
window.location.reload();
function modify_detail(obj){
$(obj).parent().prev().show();
$(obj).parent().hide();
&&#x2F;script&
&#x2F;&#x2F; 查询函数
function searchintable(){
input = document.getElementById(&search&);
filter = input.value.toUpperCase();
table = document.getElementById(&configtable&);
tr = table.getElementsByTagName(&tr&);
for(i = 0; i & tr. i++){
td = tr[i].getElementsByTagName(&td&)[0];
if (td.innerHTML.toUpperCase().indexOf(filter) & -1){
tr[i].style.display = &&;
tr[i].style.display = &none&;
&&#x2F;script&
$(document).ready(function(){
&#x2F;&#x2F;从服务器更新配置到数据库
$(&#getconfig&).click(function(){
title: &#x27;您确定要重新获取游戏配置吗?&#x27;,
type: &#x27;warning&#x27;,
confirmButtonColor: &#x27;#DD6B55&#x27;,
confirmButtonText:&是的!&,
cancelButtonText:&让我再考虑一下…&,
showLoaderOnConfirm: true, &#x2F;&#x2F;加载按钮是否可见
showCancelButton: true,
preConfirm: function() {
return new Promise(function(resolve){
setTimeout(function(){
$(&#getconfig&).hide();
$(&#search&).hide();
$(&#loading&).show();
$(&#x27;table & tbody&#x27;).remove();
resolve();
allowOutsideClick: false, &#x2F;&#x2F;弹框外是否可点
}).then(function(res){
url:&getconfig&,
type:&#x27;GET&#x27;,
success: function(arg){
ret = eval(arg);
if(ret.status){
type: &#x27;success&#x27;,
title: &#x27;更新完成!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;
}).then(function(){
window.location.reload();
type: &#x27;error&#x27;,
title: &#x27;更新失败!&#x27;,
confirmButtonText: &#x27;确定&#x27;,
confirmButtonColor: &#x27;#4cd964&#x27;
}).then(function(){
window.location.reload();
&&#x2F;script&
{% endblock %}
下面具体说下这些功能的交互。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
class serverconfig(models.Model):
id = models.AutoField(primary_key=True)
# 配置的名字
config_name = models.CharField(max_length=100)
# 配置的内容
content = models.TextField()
# 配置的描述
detail = models.CharField(max_length=200, default=&&)
class Meta:
# 别名(存储在数据库中的table名)
db_table = &#x27;serverconfig&#x27;
# 使用server数据库
app_label = &server&
依然,创建好之后需要更新django的数据表,执行python manage.py migrate --database=server。
添加渲染函数serverconfig的url(server/urls.py)
除了给出渲染函数serverconfig,这里的urls.py还写了所有后文中需要用到的相关功能url:获得配置、读取配置、修改配置、删除配置、添加配置的描述。
from django.conf.urls import url
import views
urlpatterns = [
url(r&#x27;^&#x2F;div&, views.homepage),
url(r&#x27;^home&#x27;, views.homepage),
url(r&#x27;^servertime&#x27;, views.servertime),
# 服务器配置的渲染函数
url(r&#x27;^serverconfig&#x27;, views.serverconfig),
# 相关功能函数
# 获得配置
url(r&#x27;^getconfig&#x27;, views.getconfig),
# 读取配置
url(r&#x27;^readconfig&#x27;, views.readconfig),
# 修改配置
url(r&#x27;^writeconfig&#x27;, views.writeconfig),
# 删除配置
url(r&#x27;^deleteconfig&#x27;, views.deleteconfig),
# 添加配置的描述
url(r&#x27;^configdetail&#x27;, views.configdetail),
# 以下的url在前面的文章已经实现
url(r&#x27;^settime&#x27;, views.settime),
url(r&#x27;^usingserver&#x27;, views.usingserver),
url(r&#x27;^restartserver&#x27;, views.restartserver),
url(r&#x27;^getservertime&#x27;, views.getservertime),
url(r&#x27;^recoverlocaltime&#x27;, views.recoverlocaltime),
url(r&#x27;^userlogout&#x27;, views.userlogout),
在views.py中(server/views.py)添加渲染函数servertime
页面渲染函数会将数据库中的配置通过字典传递给前端渲染,值得注意的是,这里传递给前端的只有配置的名字和它的相关描述。每个配置的展示交给前端的javascript中的getconfig单独通过ajax获取。上面给出的html中,前端页面通过模板语言,利用for循环添加到table中(tr元素)。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth import logout
from django.shortcuts import render_to_response
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
import json
import time
# 服务器的名字
htmltitle = &#x27;服务器工具&#x27;
@login_required(login_url=&#x27;&#x2F;loginpage&#x27;)
def serverconfig(request):
from server import models
username = request.session.get(&#x27;username&#x27;)
name_list = []
config_name = models.serverconfig.objects.all().values_list(&#x27;id&#x27;, &#x27;config_name&#x27;, &#x27;detail&#x27;)
for name in config_name:
name_list.append(name)
pagedict = {&#x27;name_list&#x27;: name_list, &#x27;title&#x27;: htmltitle, &#x27;username&#x27;: username}
return render_to_response(&servermaterial&#x2F;serverconfig.html&, pagedict)
添加这些功能后,就能够通过:8888/server/serverconfig.html访问这个页面了,但是我们看到的表格中没有配置,是因为网站后台还没有从服务器读取相关的配置。
从服务器获得配置
获得/更新配置
要获得这些配置需要添加相关的view函数(server/views.py),这个view函数会对比服务器中最新的配置文件和mysql中存储的配置文件的差别进行增、删、改,这个函数是通过html中的id=getconfig的按钮触发的,它的javascript函数可以在上面找到,为$(&#getconfig&).click(function(){...}),url也已经在上面给出,其对应前端页面红框中的按钮,如图5。
# 获得服务器配置
def getconfig(request):
from server import models
if request.method == &#x27;GET&#x27;:
ret = {&#x27;status&#x27;: False}
from WebTool.functions import get_serverconfig_lists, read_serverconfig
# 获得服务器中最新的配置文件名组成的列表
newconfigs = get_serverconfig_lists()
# 获得数据库中记录的未更新的老配置文件名列表
name_list = models.serverconfig.objects.all().values(&#x27;config_name&#x27;)
oldconfigs = []
for name in name_list:
oldconfigs.append(str(name[&#x27;config_name&#x27;]))
# 服务器和数据库中配置名相同的文件名,对其更新一下配置内容
common = [name for name in newconfigs if name in oldconfigs]
for config in common:
configcontent = read_serverconfig(config)
models.serverconfig.objects.filter(config_name=config).update(content=configcontent)
# 服务器中增加的配置文件名,数据库中增加一份
add_con = [name for name in newconfigs if name not in oldconfigs]
for config in add_con:
configcontent = read_serverconfig(config)
models.serverconfig.objects.create(config_name=config, content=configcontent)
# 服务器已经不存在的配置文件名,数据库删除一份
delete_con = [name for name in oldconfigs if name not in newconfigs]
for config in delete_con:
models.serverconfig.objects.filter(config_name=config).delete()
ret[&#x27;status&#x27;] = True
return JsonResponse(ret)
所有的配置文件都放在如下图6所示的服务器目录中,网站后台通过调用funtions.py中的函数(这些paramiko函数在文章中已经封装好了)获得这些配置的名字。
如果要实现键盘弹起就进行搜索可以参考,在input中加入onkeyup这个性质,图7中红色的搜索框的html代码如下:
&input type=&text& class=&form-control& onkeyup=&searchintable()& id=&search& placeholder=&配置搜索&&
searchintable()函数如下,加入函数之后便可以实现在搜索框中一边输入一边搜索配置。
&#x2F;&#x2F; 查询函数
function searchintable(){
input = document.getElementById(&search&);
filter = input.value.toUpperCase();
table = document.getElementById(&configtable&);
tr = table.getElementsByTagName(&tr&);
for(i = 0; i & tr. i++){
td = tr[i].getElementsByTagName(&td&)[0];
if (td.innerHTML.toUpperCase().indexOf(filter) & -1){
tr[i].style.display = &&;
tr[i].style.display = &none&;
&&#x2F;script&
前端读取配置
读取、修改、删除的按钮在图8的红框中。
点击绿色的查看按钮会弹出只读的模态框,如图9所示。
读取配置的模态框,配置文件写在textarea中,readonly=&readonly&可将其设置为只读模式:
&div class=&modal fade& id=&readModal& tabindex=&-1& role=&dialog& aria-labelledby=&myModalLabel& aria-hidden=&true&&
&div class=&modal-dialog&&
&input type=&hidden& name=&#x27;modal&#x27; value=&#x27;&#x27;&
&div class=&modal-content&&
&div class=&modal-header&&
&button type=&button& class=&close& data-dismiss=&modal& aria-hidden=&true&&
&&#x2F;button&
&h4 class=&modal-title& id=&myModalLabelread&&
模态框(Modal)标题
&&#x2F;h4&
&&#x2F;div&
&!--style=&cursor:default& 设置只读状态--&
&textarea type=&text& class=&form-control modal-body-read& rows=&35& placeholder=&& readonly=&readonly& style=&cursor:default&&
在这里添加一些文本
&&#x2F;textarea&
&div class=&modal-footer&&
&button type=&button& class=&btn btn-theme02& data-dismiss=&modal&&关闭
&&#x2F;button&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
读取配置的view函数,函数直接在数据库中按名字查找配置的具体内容。
# get config content
def readconfig(request):
ret = {&#x27;status&#x27;: False, &#x27;content&#x27;: &#x27;&#x27;}
if request.method == &#x27;POST&#x27;:
from server import models
name = request.POST.get(&#x27;configname&#x27;)
content = models.serverconfig.objects.get(config_name=name).content
ret[&#x27;status&#x27;] = True
ret[&#x27;content&#x27;] = content
return JsonResponse(ret)
return JsonResponse(ret)
前端修改配置
点击蓝色的修改按钮会弹出修改配置的模态框,如下图10。
读取配置的模态框,配置文件写在textarea中,并为其添加一个提交按钮:
&div class=&modal fade& id=&writeModal& tabindex=&-1& role=&dialog& aria-labelledby=&myModalLabel& aria-hidden=&true&&
&div class=&modal-dialog&&
&input type=&hidden& id=&#x27;configname&#x27; name=&#x27;modal&#x27; value=&#x27;&#x27;&
&div class=&modal-content&&
&div class=&modal-header&&
&button type=&button& class=&close& id=&closebtn1& data-dismiss=&modal& aria-hidden=&true&&
&&#x2F;button&
&h4 class=&modal-title& id=&myModalLabelwrite&&
模态框(Modal)标题
&&#x2F;h4&
&&#x2F;div&
&div class=&progress progress-striped active& style=&display:& id=&writeloading&&
&div class=&progress-bar& role=&progressbar& aria-valuenow=&100& aria-valuemin=&0& aria-valuemax=&100& style=&width: 100%&&&&#x2F;div&
&&#x2F;div&
&textarea type=&text& class=&form-control modal-body-write& rows=&35& placeholder=&&&&&#x2F;textarea&
&div class=&modal-footer&&
&button type=&button& class=&btn btn-theme03& id=&putconfigbtn& onclick=&putconfig()&&提交&&#x2F;button&
&button type=&button& class=&btn btn-theme02& id=&closebtn2& data-dismiss=&modal&&关闭&&#x2F;button&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
&&#x2F;div&
点击提交按钮会出现swal风格(插件在文章中介绍过)的二次确认框,如上图9。ajax请求经过server/urls.py中的url找到server/views.py中的writeconfig函数。因为文中的配置都是json格式的,如果格式不符合json要求会无法修改。这里有个缺点,修改服务器配置的函数generate_config_upload_file实际上只是在本地生成一个字符串然后上传覆盖掉服务器的同文件名的配置,并不是局部修改,所以对于大的配置文件修改效率低,但是为了方便就直接这样做了。
# write config
def writeconfig(request):
ret = {&#x27;status&#x27;: False, &#x27;error&#x27;: &#x27;&#x27;, &#x27;oldcontent&#x27;: &#x27;&#x27;}
if request.method == &#x27;POST&#x27;:
from server import models
from WebTool.functions import generate_config_upload_file
name = request.POST.get(&#x27;name&#x27;)
newcontent = request.POST.get(&#x27;content&#x27;)
json.loads(newcontent)
except ValueError:
oldcontent = models.serverconfig.objects.get(config_name=name).content
ret[&#x27;oldcontent&#x27;] = oldcontent
ret[&#x27;error&#x27;] = &#x27;1&#x27;
return JsonResponse(ret)
rtn = generate_config_upload_file(name, newcontent)
if rtn == &#x27;Successful Upload&#x27;:
models.serverconfig.objects.filter(config_name=name).update(content=newcontent)
ret[&#x27;status&#x27;] = True
return JsonResponse(ret)
oldcontent = models.serverconfig.objects.get(config_name=name).content
ret[&#x27;oldcontent&#x27;] = oldcontent
ret[&#x27;error&#x27;] = &#x27;2&#x27;
return JsonResponse(ret)
删除配置就更简单了,点击红色的按钮可以唤出二次确认框,如图11,然后ajax请求经过server/urls.py中的url找到server/views.py中的deleteconfig函数执行删除。
# delete config
def deleteconfig(request):
ret = {&#x27;status&#x27;: False}
if request.method == &#x27;POST&#x27;:
from server import models
from WebTool.functions import delete_config
name = request.POST.get(&#x27;name&#x27;)
models.serverconfig.objects.filter(config_name=name).delete()
delete_config(name)
ret[&#x27;status&#x27;] = True
return JsonResponse(ret)
except Exception:
ret[&#x27;status&#x27;] = False
return JsonResponse(ret)
服务器配置文件修改基本上就实现了,下篇文章会说说websocket原理以及怎么利用websocket执行实时日志的查看。
你可能感兴趣的文章:
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果
首先要确认前端使用页面,比如...
&font face=&寰?杞?闆呴粦, Arial, sans-serif &&2014骞达紝杞?浠惰?屼笟鍙戝睍杩呴EUR燂紝鍚勭?嶈??瑷EUR灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘EUR傝繖浜涜??...
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。
1.CSS的color属性并非只能用于文本显示
对于CSS的color属性,相信所有Web开发人员...
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。
Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改:
&template...
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。
标准方法(The Standard Way)
一直以来,我们学习的在 JavaScript 里创建对...
AJAX 的要点是 XMLHttpRequest 对象。
不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。
IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 Jav...
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。
Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
typeof:以字符串的形式返回变量的原始类型,typeof在两种情况下会返回&undefined&:一个变量没有被声明的时候,和一个变量的值是undefined的时候,注意,typeof null也会返回object,...
微信公众号搜索: FedJavaScript ,选择关注,与十万前端开发者一起探讨前端学习
扫描下方二维码回复 1024 获取验证码
验证码有误,请重新输入
本站(www.javascriptcn.com)所提供的等资源来源互联网,仅供学习研究之用,版权归该资源的合法拥有者所有,如用于商业用途,请购买正版,原作者若认为本站侵犯了您的版权,请联系我们,我们会立即删除!
鄂ICP备号-1
没有账号?}

我要回帖

更多关于 django 动态路由 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信