Django大而全;
创建Django工程:django-admin startproject sitename
Project
Project
settings
url
wsgi
web
model
views
test
admin
administrator
D:\python_scripts\s11day17_Django>python manage.py startapp app01 #创建app;一个app是一个完整的软件或者功能;
app下面的文件:
models:对数据库操作的;
views:函数放置的文件;
test:做测,忽略;
admin:Django的后台管理平台;
http://127.0.0.1:8000/admin 访问Django的后台管理平台;
可以创建admin后台管理的账户,账户默认存在于数据库下,存放位置在settings中定义如下:
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.sqlite3‘, ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘), }} 下面写一个http请求,urls是路由系统:
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, include(admin.site.urls)), url(r‘^home/‘,views.home), #一个url对应一个函数,函数存在于app的views中] views中的函数如下:
from django.shortcuts import render # Create your views here.from django.shortcuts import HttpResponsedef home(request): #此处的request是必须的 return HttpResponse(‘ok‘)
D:\python_scripts\s11day17_Django>python manage.py runserver 127.0.0.1:8009 #启动Django程序;或者在Django工程的edit下面配置端口http://127.0.0.1:8009/home/ #访问
http请求完毕; Django模板渲染在app的views中添加的函数返回html文件内容,如下:
#!/usr/bin/env python#coding:utf-8from django.shortcuts import render # Create your views here.from django.shortcuts import HttpResponsedef home(request): #return HttpResponse(‘ok‘) ‘‘‘render内部找到home.html,读取html返回给用户,render和跨站请求伪造相关‘‘‘ return render(request,‘home.html‘)
可以看到默认到templates模块下找该文件了;那么程序如何知道html文件时在templates下面去找的呢?事实上,是在settings配置文件下面设置的啦;不同版本的Django配置有所不同;
TEMPLATES = [ { ‘BACKEND‘: ‘django.template.backends.django.DjangoTemplates‘, ‘DIRS‘: [os.path.join(BASE_DIR, ‘templates‘)] ,
就OK拉~~~~~~~ Django内部也使用jinjia2模板:views内容如下:
#!/usr/bin/env python#coding:utf-8# Create your views here.from django.shortcuts import renderfrom django.shortcuts import HttpResponse,render_to_responsedef home(request): #return HttpResponse #return render_to_response(request,‘home.html‘) ‘‘‘render内部找到home.html,读取html返回给用户‘‘‘ dic ={‘name‘:‘Charles‘,‘age‘:18} return render(request,‘home.html‘,dic)
home.html文件如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title></head><body> <h1>Home</h1> <h2>{{ name }}</h2> <h2>{{ age }}</h2></body></html> 模板渲染完毕 模板语言和自定义simple_taghome.html模板语言:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title></head><body> <h1>Home</h1> <h2>{{ name }}</h2> <h2>{{ age }}</h2> <ul> {% for item in user_list %} <li>{{ item }},{{ forloop.first }}</li> {% endfor %} </ul></body></html> views内容如下:
#!/usr/bin/env python#coding:utf-8# Create your views here.from django.shortcuts import renderfrom django.shortcuts import HttpResponse,render_to_responsedef home(request): #return HttpResponse #return render_to_response(request,‘home.html‘) ‘‘‘render内部找到home.html,读取html返回给用户‘‘‘ dic ={‘name‘:‘Charles‘,‘age‘:18,‘user_list‘:{‘Charles‘,‘wahaha‘,‘Rain‘}} return render(request,‘home.html‘,dic)
尽管模板语言可以提供部分函数,实现一部分功能,但是有些需要我们自定义区实现:1、在app中创建templatetags和文件
2、
3、
Django之母版:什么叫做母版:红色部分在其他页面走不回改变,那么就没有必要再任何页面写这些内容啦~~~,可以创建母版实现啦,类似于类的继承
那么如何实现母版以及继承母版:
master下的m1为母版:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <style> .header{ height: 48px; background-color: red; } .body{ background-color: #dddddd; } .body .menu{ background-color: green; float: left; width: 2%; } .body .content{ background-color: darkgoldenrod; float: left; width: 70%; } </style></head><body> <div class="header">LOGO</div> <div class="body"> <div class="menu">左侧菜单</div> <div class="content"> {% block content %}{% endblock %} </div> </div></body></html> son1继承m1:
{% extends "master/m1.html" %}{% block content %} <h1>666</h1> {% include "include/input_group.html" %} {% include "include/haha.html" %}{% endblock %} {% block title %} 老男人{% endblock %} son1同样继承include下的两个html文件内容;include防止在子html的什么位置,内容就显示在什么地方; 母版和include的应用场景: 母版:总体布局使用;include在局部功能上需要别的页面继承的时候使用:
views的内容:
#!/usr/bin/env python#coding:utf-8# Create your views here.from django.shortcuts import renderfrom django.shortcuts import HttpResponse,render_to_response def son(request): return render(request,‘son1.html‘)def home(request): #return HttpResponse #return render_to_response(request,‘home.html‘) ‘‘‘render内部找到home.html,读取html返回给用户‘‘‘ dic ={‘name‘:‘Charles‘,‘age‘:18,‘user_list‘:{‘Charles‘,‘wahaha‘,‘Rain‘}} return render(request,‘home.html‘,dic) urls的内容:
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, include(admin.site.urls)), url(r‘^home/‘,views.home), url(r‘^son/‘,views.son),] Django静态文件的配置:比如上面html母版中的CSs渲染的部分,需要放置到静态文件夹中,然后在母版中导入即可;创建static静态文件夹
在settings中指明(需要一一对应)文件的路径
这样母版m1的内容就为:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <link rel="stylesheet" href="/static/css/commons.css"/> {% block css %}{% endblock %} #也可以设置css文件的母版</head><body> <div class="header">LOGO</div> <div class="body"> <div class="menu">左侧菜单</div> <div class="content"> {% block content %}{% endblock %} </div> </div> <script type="text/javascript"> </script> {% block js %}{% endblock %} #设置js文件的母版</body></html> commons.ss的内容为:
.clearfix:after{ content: "."; visibility: hidden; display: block; height: 0; clear: both;}.header{ height: 48px; background-color: red; } .body{ background-color: #dddddd; } .body .menu{ background-color: green; float: left; width: 2%; } .body .content{ background-color: darkgoldenrod; float: left; width: 70%; } settings的内容如下:
STATIC_URL = ‘/static/‘STATICFILES_DIRS=( os.path.join(BASE_DIR,‘static‘),)
整个程序访问流程如下:请求到url-->views-->templates中找html-->数据和html模板渲染-->得到字符串返回给用户 下面开发一个Django用户登录实例:1、拷贝jQuery和bootstrap插件到静态文件目录下:
2、增加登录模块(html文件),增加表单的name
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>登录</title> <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"/></head><body> <div class="container"> <form class="form-horizontal" action="/login/" method="post"> #action表示将数据提交到该函数; <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">Email</label> <div class="col-sm-10"> <input type="email" name="email" class="form-control" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">Password</label> #email和pwd <div class="col-sm-10"> <input type="password" name="pwd" class="form-control" placeholder="Password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox"> Remember me </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">Sign in</button> <span style="color: red;">{{ status }}</span> #登录失败时候的渲染 </div> </div> </form> </div> <script type="text/javascript" src="/static/js/jquery-2.1.4.min.js"></script> <script type="text/javascript" src="/static/plugins/bootstrap/js/bootstrap.js"></script></body></html> 3、views增加login函数
def login(request): #如果是get请求,get请求表示请求页面 #如果是POST,检验用户输入;POST表示向页面提交内容 print request.method if request.method == ‘POST‘: input_email=request.POST[‘email‘] input_pwd = request.POST[‘pwd‘] if input_email == ‘[email protected]‘ and input_pwd == "123": from django.shortcuts import redirect return redirect("https://www.baidu.com") #跳转到别的页面,如果想要跳转到别的函数,比如son,return redirect("/son/")
else: return render(request,‘login.html‘,{‘status‘:‘用户名或密码错误‘}) #否则显示错误 return render(request,‘login.html‘)
4、urls的内容
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, include(admin.site.urls)), url(r‘^home/‘,views.home), url(r‘^son/‘,views.son), url(r‘^login/‘,views.login),] model基本操作之增删改查Django提供了ORM,可以使用类来创建数据库表和字段:
命令python manage.py makemigations 和python manage.py migrate可以创建数据表,生成0001.initial.py文件(注意都是在app01中操作的)2、settings内容:
INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app01‘, #注册该app]
3、urls内容
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, include(admin.site.urls)), url(r‘^home/‘,views.home), url(r‘^son/‘,views.son), url(r‘^login/‘,views.login), url(r‘^index/‘,views.index),]4、views中定义index函数:
#!/usr/bin/env python#coding:utf-8# Create your views here.from django.shortcuts import renderfrom django.shortcuts import HttpResponse,render_to_response def son(request): return render(request,‘son1.html‘)def home(request): #return HttpResponse #return render_to_response(request,‘home.html‘) ‘‘‘render内部找到home.html,读取html返回给用户‘‘‘ dic ={‘name‘:‘Charles‘,‘age‘:18,‘user_list‘:{‘Charles‘,‘wahaha‘,‘Rain‘}} return render(request,‘home.html‘,dic) def login(request): #如果是get请求 #如果是POST,检验用户输入 print request.method if request.method == ‘POST‘: input_email=request.POST[‘email‘] input_pwd = request.POST[‘pwd‘] if input_email == ‘[email protected]‘ and input_pwd == "123": from django.shortcuts import redirect return redirect("/index/") else: return render(request,‘login.html‘,{‘status‘:‘用户名或密码错误‘}) return render(request,‘login.html‘) def index(request): #数据库取数据 #数据和HTML渲染 from app01 import models if request.method =="POST": input_em = request.POST[‘em‘] input_pw = request.POST[‘pw‘] models.UserInfo.objects.create(email=input_em,pwd=input_pw) #增加数据 #models.UserInfo.objects.filter(email=input_em).delete() #删除数据 #models.UserInfo.objects.filter(email=input_em).update(pwd=999) #更新数据 #获取UserInfo表中的所有的数据 user_info_list = models.UserInfo.objects.all() #查收,在模板中循环 #user_info_list列表,列表的元素为一行;email,pwd; return render(request,‘index.html‘,{‘user_info_list‘:user_info_list})
4、模板index.html内容
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <form action="/index/" method="post"> <input type="text" name="em"/> <input type="text" name="pw"/> <input type="submit" name="添加"/> </form> <table border="1"> <thead> <tr> <th>邮箱</th> <th>密码</th> </tr> </thead> <tbody> {% for line in user_info_list %} <tr> <td>{{ line.email }}</td> <td>{{ line.pwd }}</td> </tr> {% endfor %} </tbody> </table></body></html>
--权限登录管理系统 1、登录(装饰器判断用户是否已经登录--可选,用户密码MD5) 2、注册(检测用户是否已经存在,onblur+ajax光标跳出输入框时) 3、注销(忽略) 4、用户管理(From表单) 重置密码 创建用户(单条,批量) 修改用户信息 5、权限控制(可选) 用户是否可以访问URL
作业
内容:一、URL路由系统二、中间件三、Model:数据库的操作(重点) 1、创建表 2、操作表数据四、Form(重点) 1、用户提交数据验证 2、生成html标签五、cookie和session六、跨站请求伪造和跨站脚本攻击七、Ajax操作(重点)八、Admin九、缓存十、自定义分页(重点) 下面分开介绍: Django请求生命周期
路由系统详细介绍: 分页的概念:
点击是url发生变化; 那么如何实现分页:路由系统函数传参
1、urls的内容:
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^app01/‘, include("app01.urls")), url(r‘^index/$‘, views.index), #url(r‘^user_list/(\d+)$‘, views.user_list), #django内部默认将url以/为分割线将url分割,传入参数,默认是按照顺序传入参数的 #url(r‘^user_list/(\d+)/(\d+)$‘, views.user_list), url(r‘^user_list/(?P<v1>\d+)/(?P<v2>\d+)$‘, views.user_list), #要灵活传入参数,设置(?P<v1>\d+),v1表示key,传入的参数为value
url(r‘^$‘, views.index), #放置到最后] 2、views的内容
from django.shortcuts import render,HttpResponse # Create your views here.def index(request): return HttpResponse(‘OK‘) def user_list(request,v2,v1): #将key传入 print v1,v2 return HttpResponse(v1+v2)
对于不同的app而言,如何实现输入url为app01的请求发送到app01上面:
1、urls的内容
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^app01/‘, include("app01.urls")), #发送的对应app下的urls中 url(r‘^index/$‘, views.index), #url(r‘^user_list/(\d+)$‘, views.user_list), #url(r‘^user_list/(\d+)/(\d+)$‘, views.user_list), url(r‘^user_list/(?P<v1>\d+)/(?P<v2>\d+)$‘, views.user_list), url(r‘^$‘, views.index), #放置到最后,为路由系统的默认处理函数,类似于404]2、在app01下新建urls文件
3、settings
INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app01‘]
访问:
Django路由系统完毕!!!
基于反射的路由系统:多有的函数都放置在一个.py文件中;
中间件:
Django提供的中间件如下:
MIDDLEWARE_CLASSES = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,]
自定义中间件来解析中间件工作流程:
1、创建中间件文件夹以及文件
middle文件内容为:
#!/usr/bin/env python# _*_ coding:utf-8 _*_class mmm(object): def process_view(self, request, callback, callback_args, callback_kwargs): print ‘mmm.process_view‘ def process_response(self, request, response): print ‘mmm.process_response‘ return responseclass xxx(object): #类中的函数上面两个方法是必须要有的,只能存在这四个方法 def process_request(self,request): print ‘xxx.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘xxx.process_view‘ def process_response(self, request, response): print ‘xxx.process_response‘ return response def process_exception(self,request,exception): pass
2、注册中间件到settings文件中
MIDDLEWARE_CLASSES = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ‘middleware.middle.mmm‘, ‘middleware.middle.xxx‘,] 3、views内容如下:
from django.shortcuts import render,HttpResponse # Create your views here.def index(request): print ‘index‘ return HttpResponse(‘OK‘) def user_list(request,v2,v1): print v1,v2 return HttpResponse(v1+v2) 4、访问如下:
process_expection方法在views.index函数执行出错的时候触发; 总结:1、客户端发出请求2、Django自动去settings中找MIDDLEWARE_CLASSES,列表或元组process_request_list = []process_view_list = []process_response_list = []process_exception_list = []3、for 类 in MIDDLEWARE_CLASSES: obj=类() if obj 里有process_request方法: process_request_list.append(obj.process_request_list)
if obj 里有process_view方法: process_view_list.append(obj.process_request_list)
views中的函数:
if obj 里有process_response方法:
process_response_list .append(obj.process_request_list)中间件是一个类,类中的方法名必须是固定的
1、 #process_request和process_view没有返回值,是正常的执行过程(蓝色部分)
class xxx(object): def process_request(self,request): print ‘xxx.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘xxx.process_view‘ def process_response(self, request, response): print ‘xxx.process_response‘ return response def process_exception(self,request,exception): pass2、request函数直接返回值,为红色部分3、灰色部分表示函数执行出错的时候的执行流程; 下面展示process_exception;settings的内容:
MIDDLEWARE_CLASSES = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ‘middleware.middle.mmm‘, ‘middleware.middle.xxx‘,] middle.py内容:
#!/usr/bin/env python# _*_ coding:utf-8 _*_ from django.shortcuts import render,HttpResponse class mmm(object): def process_request(self,request): print ‘mmm.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘mmm.process_view‘ def process_response(self, request, response): print ‘mmm.process_response‘ return response def process_exception(self,request,exception): print ‘View中出错了返回‘ return HttpResponse(‘View中出错了,返回‘)class xxx(object): def process_request(self,request): print ‘xxx.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘xxx.process_view‘ def process_response(self, request, response): print ‘xxx.process_response‘ return response def process_exception(self,request,exception): print ‘View中出错了,但是不返回‘ return HttpResponse(‘View中出错了,不返回‘) #第二个函数返回,将不会执行第一个函数
直接返回
midele.py第二个函数没有返回值:那么两个函数执行都会执行;
#!/usr/bin/env python# _*_ coding:utf-8 _*_ from django.shortcuts import render,HttpResponse class mmm(object): def process_request(self,request): print ‘mmm.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘mmm.process_view‘ def process_response(self, request, response): print ‘mmm.process_response‘ return response def process_exception(self,request,exception): print ‘View中出错了返回‘ return HttpResponse(‘View中出错了,返回‘)class xxx(object): def process_request(self,request): print ‘xxx.process_request‘ def process_view(self, request, callback, callback_args, callback_kwargs): print ‘xxx.process_view‘ def process_response(self, request, response): print ‘xxx.process_response‘ return response def process_exception(self,request,exception): print ‘View中出错了,但是不返回‘
总结:process_exception函数根据setting的设置从下往上执行,如果有返回值,就不会执行后面的类中的process_exception函数; 缓存介绍:将DB和templates中拿到的渲染后的字符串,放置到缓存中,缓存的介质可以为文件、memcached、redis、数据库;
使用缓存步骤:1、views中添加如下函数:
def cache_page(request): current = str(time.time()) return HttpResponse(current) app01\urls内容为:
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^index/‘, views.index), url(r‘^cache/‘, views.cache_page),]每次post请求的时候,其内容都会重新渲染,显示不同的字符串
3、在settings配置文件中添加如下内容:
CACHES = { ‘default‘: { ‘BACKEND‘: ‘django.core.cache.backends.filebased.FileBasedCache‘, ‘LOCATION‘: os.path.join(BASE_DIR, ‘cache‘), #缓存内容使用文件,存放在文件里面 ‘TIMEOUT‘: 600, ‘OPTIONS‘: { ‘MAX_ENTRIES‘: 1000 } }}
4、给views中的函数增加装饰器
from django.shortcuts import render,HttpResponseimport timefrom django.views.decorators.cache import cache_page@cache_page(60 * 15) #表示每15分钟缓存更新一次;def cache_page(request): current = str(time.time()) return HttpResponse(current)
下面介绍cookie和session:
1、cookie是一个字符串,保存于本地的电脑上;session保存于服务器
因为http是短连接,第一次访问之后就会断开,那么第二次访问的时候如何知道之前该用户已经访问过了;比如要访问jd的页面,第一次登陆之后,服务器端会向客户端浏览器下发一个字符串,第二次用户访问的时候就可以携带者这个字符串来访问了,这样服务器端就认为已经登陆过了,就可以允许用户点击购物车等其他链接了;那么问题来了,服务器如何根据字符串判断用户已经访问过了?
上述步骤中1和2是web框架自己实现的,第3步中,对用户的session设置对应的任意值是程序员自己设置的,比如,此处可以设置为是否登录is_login;具体实现如下:a、app01中views增加函数如下:
def login(request): if request.method==‘POST‘: username = request.POST.get(‘username‘) pwd = request.POST.get(‘pwd‘) if username == ‘Charles‘ and pwd==‘123‘: request.session[‘IS_LOGIN‘] = True return redirect(‘/app01/home/‘) return render(request,‘login.html‘) def home(request): ‘‘‘ 如果用户已经登陆 ‘‘‘ is_login = request.session.get(‘IS_LOGIN‘,False) if is_login: return HttpResponse(‘order‘) else: return redirect(‘/app01/login/‘)b、app01\urls
from django.conf.urls import url,includefrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r‘^index/$‘, views.index), url(r‘^cache/$‘, views.cache_page), url(r‘^login/$‘, views.login), url(r‘^home/$‘, views.home), ]c、templates中定义login.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title></head><body> <form action="/app01/login/" method="post"> <input type="text" name="username"/> <input type="password" name="pwd"> <input type="submit" value="submit"/> </form></body></html> 注意:session是存在于数据库中的,如果变化session内容(request.session[‘IS_LOGIN‘] = True),那么就需要重新同步数据库:D:\python_scripts\s11day18_Django>python manage.py migrated、如果用户名和密码不正确,就会报403错误,需要禁止掉csrf
MIDDLEWARE_CLASSES = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, #‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ‘middleware.middle.mmm‘, ‘middleware.middle.xxx‘,]
注意:默认情况下,Django的session存放在数据库中;
这样我们可以通过自定义session,来根据输入的不同的用户,显示不同的值;
db = { ‘Charles‘:‘11111‘, ‘eric‘:‘22222‘,}
def login(request): if request.method==‘POST‘: username = request.POST.get(‘username‘) pwd = request.POST.get(‘pwd‘) if username == ‘Charles‘ and pwd==‘123‘: request.session[‘IS_LOGIN‘] = True request.session[‘USERNAME‘]=‘Charles‘ return redirect(‘/app01/home/‘) elif username==‘eric‘ and pwd ==‘123‘: request.session[‘IS_LOGIN‘] = True request.session[‘USERNAME‘]=‘eric‘ return redirect(‘/app01/home/‘) return render(request,‘login.html‘) def home(request): ‘‘‘ 如果用户已经登陆 ‘‘‘ is_login = request.session.get(‘IS_LOGIN‘,False) if is_login: username = request.session.get(‘USERNAME‘,False) data = db[username] return HttpResponse(data) else: return redirect(‘/app01/login/‘)
如何在右上角设置登录和注销的按钮:在登录之后,将用户名和注销的按钮显示在右上角a、app01/views增加函数:
views
def login(request): if request.method==‘POST‘: username = request.POST.get(‘username‘) pwd = request.POST.get(‘pwd‘) if username == ‘Charles‘ and pwd==‘123‘: request.session[‘IS_LOGIN‘] = True request.session[‘USERNAME‘]=‘Charles‘ return redirect(‘/app01/home/‘) elif username==‘eric‘ and pwd == ‘123‘: request.session[‘IS_LOGIN‘] = True request.session[‘USERNAME‘]=‘eric‘ return redirect(‘/app01/home/‘) return render(request,‘login.html‘) def home(request): ‘‘‘ 如果用户已经登陆 ‘‘‘ is_login = request.session.get(‘IS_LOGIN‘,False) if is_login: username = request.session.get(‘USERNAME‘,False) data = db[username] #return HttpResponse(data) return render(request,‘home.html‘,{‘username‘:username}) else: return redirect(‘/app01/login/‘) def logout(request): del request.session[‘IS_LOGIN‘] return redirect(‘/app01/login‘)
b、templates下增加html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .header{ height: 48px; } </style> </head> <body> <div class="header"> <div style="float: right">{{ username }}</div> <div style="float: right"><a href="/app01/logout/">注销</a></div> </div> </body> </html>
home.html
c、app01/urls内容:
from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r‘^index/$‘, views.index), url(r‘^cache/$‘, views.cache_page), url(r‘^login/$‘, views.login), url(r‘^home/$‘, views.home), url(r‘^logout/$‘, views.logout), ]
urls
cookie可是设置超时时间,在settings文件中,增加字段:SESSION_COOKIE_AGE = 5,表示cookie超时时间为5秒,也可以设置关闭会话后,删除cookie;上述页面在cookie删除之后会自动跳转到登录页面(然而我测试没有成功/(ㄒoㄒ)/~~)
cookie和session到此结束,O(∩_∩)O~; 下面介绍Django From;作用:1、用户提交数据验证;2、生成html标签;为什么要使用From,看下面:a、app01/views中定义函数:
def user_list(request): # host = request.POST.get(‘host‘) # port = request.POST.get(‘port‘) #email = request.POST.get(‘email‘) #mobile = request.POST.get(‘mobile‘) #‘‘‘上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的 #工作才能够实现‘‘‘ #return render(request,‘user_list.html‘)
views.py
b、定义html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} {% comment %} <input type="text" name="host"/> <input type="text" name="port"/> <input type="text" name="email"/> <input type="text" name="mobile"/> <input type="submit" value="submit" />{% endcomment %} </form> </body> </html>
user_list.html
上述例子中需要程序员需要解决两个问题:1、严重用户输入的内容各项不能为空;2、验证用户输入的各项内容是否合法;这两项工作都需要做大量的工作;而From不但可以自动实现验证功能,还可以自动生成html标签; 除此以外,前端js验证如果js被客户端浏览器禁用掉的话,无法使用,所有最好前端和后台验证都各写一套;
前端js实现验证功能实例如下:
具体实现如下:
a、views的内容:
#!/usr/bin/env python #coding:utf-8 from django.shortcuts import render # Create your views here. from django import forms class UserInfo(forms.Form): #email = forms.EmailField(required=False) email = forms.EmailField() host = forms.CharField() port = forms.CharField() mobile=forms.CharField() def user_list(request): obj = UserInfo() if request.method=="POST": user_input_obj = UserInfo(request.POST) #用户输入的各项字段的值 #print user_input_obj.is_valid() if user_input_obj.is_valid(): #判断各项输入是否合法 data = user_input_obj.clean() #用户输入的各项的值,为字典类型 print data else: error_msg = user_input_obj.errors print error_msg return render(request,‘user_list.html‘,{‘obj‘:user_input_obj,‘errors‘:error_msg}) return render(request,‘user_list.html‘,{‘obj‘:obj}) # host = request.POST.get(‘host‘) # port = request.POST.get(‘port‘) #email = request.POST.get(‘email‘) #mobile = request.POST.get(‘mobile‘) #‘‘‘上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的 #工作才能够实现‘‘‘ #return render(request,‘user_list.html‘)
app01/views
b、user_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} <p>主机: {{ obj.host }}<span>{{ errors.host }} #如果输入不合法,将错误信息显示出来</span></p> <p>端口: {{ obj.port }}<span>{{ errors.port }}</span></p> <p>邮箱: {{ obj.email }}<span>{{ errors.email }}</span></p> <p>手机: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p> <input type="submit" value="submit" /> {% comment %} <input type="text" name="host"/> <input type="text" name="port"/> <input type="text" name="email"/> <input type="text" name="mobile"/> <input type="submit" value="submit" />{% endcomment %} </form> </body> </html>
user_list.html
c、
MIDDLEWARE_CLASSES = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, # ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ]
禁止csrf功能
"""s11day18_form URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.9/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r‘^$‘, views.home, name=‘home‘) Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r‘^$‘, Home.as_view(), name=‘home‘) Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r‘^blog/‘, include(‘blog.urls‘)) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^user_list/‘, views.user_list), ]
urls
输入合法与不合法显示信息如下:
Django From定制化在上面的例子中,我们只是简单实现了from自动生成html标签和from表单验证的功能,那么对于一些个性化的表单验证和错误信息的展示,该如何实现呢?1、views的内容:
#!/usr/bin/env python #coding:utf-8 from django.shortcuts import render # Create your views here. from django import forms from django.core.exceptions import ValidationError import re def mobile_validate(value): mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘) #个性化定制验证功能,是否符合手机号码规则 if not mobile_re.match(value): raise ValidationError(‘手机号码格式错误‘) class UserInfo(forms.Form): #通过定义类。实现获取用户输入表单的信息 user_type_choice = ( (0, u‘普通用户‘), (1, u‘高级用户‘), ) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, #实现select选择功能 attrs={‘class‘: "form-control"})) #email = forms.EmailField(required=False) email = forms.EmailField(error_messages={‘required‘: u‘邮箱不能为空‘}) host = forms.CharField(error_messages={‘required‘: u‘主机名不能为空‘}) port = forms.CharField(error_messages={‘required‘: u‘端口不能为空‘}) mobile=forms.CharField(validators=[mobile_validate, ], #验证手机号码 error_messages={‘required‘: u‘手机不能为空‘}, widget=forms.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘手机号码‘})) memo = forms.CharField(required=False, max_length=256, widget=forms.Textarea(attrs={‘class‘: "form-control", #attrs表示想input中添加属性 ‘placeholder‘: u‘备注‘})) def user_list(request): obj = UserInfo() if request.method=="POST": user_input_obj = UserInfo(request.POST) #print user_input_obj.is_valid() if user_input_obj.is_valid(): data = user_input_obj.clean() print data else: error_msg = user_input_obj.errors print error_msg return render(request,‘user_list.html‘,{‘obj‘:user_input_obj,‘errors‘:error_msg}) return render(request,‘user_list.html‘,{‘obj‘:obj}) # host = request.POST.get(‘host‘) # port = request.POST.get(‘port‘) #email = request.POST.get(‘email‘) #mobile = request.POST.get(‘mobile‘) #‘‘‘上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的 #工作才能够实现‘‘‘ #return render(request,‘user_list.html‘)
views.py
2、html文件内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %} background-color: red; } </style> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} <p>用户类型: {{ obj.user_type }}<span>{{ errors.user_type }}</span></p> <p>主机: {{ obj.host }}<span>{{ errors.host }}</span></p> <p>端口: {{ obj.port }}<span>{{ errors.port }}</span></p> <p>邮箱: {{ obj.email }}<span>{{ errors.email }}</span></p> <p>手机: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p> <p>备注: {{ obj.memo }}<span>{{ errors.mome }}</span></p> <input type="submit" value="submit" /> </form> </body> </html>
user_list.html
总结:
1、创建类from.From 2、页面根据类的对象自动创建html标签 3、提交数据,request.POST 封装到一个类的对象里 obj=UserInfo(request.POST) 4、用户输入是否合法 obj.is_valid() 5、全部合法的话,得到用户输入数据 obj.clean() 6、只要有一个不合法,产生不合法的错误提示信息 obj.errors 注意:自定义的UserInfo类中可以写入select插件,可以通过attr添加属性,可以通过正则表达式这是输入数据的格式;
总结
Form漂亮的显示错误信息 form默认生成的html错误信息是ul,前面带黑点;使用as_data()来讲ul转换为原生的字符串;
def user_list(request): obj = UserInfo() if request.method=="POST": user_input_obj = UserInfo(request.POST) #print user_input_obj.is_valid() if user_input_obj.is_valid(): data = user_input_obj.clean() print data else: error_msg = user_input_obj.errors.as_data() #默认为ul,前面加黑点,使用as_data()将其转换为原生的字符串显示 print error_msg return render(request,‘user_list.html‘,{‘obj‘:user_input_obj,‘errors‘:error_msg}) return render(request,‘user_list.html‘,{‘obj‘:obj}
views
上述错误信息是包含在字典当中,但是在模板语言中,无法通过索引如host[0][0]来获取到错误信息,这时候就需要借助是、simple_tag来实现通过python的索引类获取错误信息了;
INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app01‘, ]
settings
#!/usr/bin/env python # -*- coding:utf-8 -*- from django import template from django.utils.safestring import mark_safe from django.template.base import resolve_variable, Node, TemplateSyntaxError register = template.Library() from django import template from django.utils.safestring import mark_safe from django.template.base import resolve_variable, Node, TemplateSyntaxError register = template.Library() @register.simple_tag def error_message(arg): if arg: return arg[0][0] #通过索引取值 else: return ‘‘
form_tag
{% load form_tag %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %} background-color: red; } </style> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} <p>用户类型: {{ obj.user_type }} <span>{% error_message errors.user_type %}</span> </p> <p>主机: {{ obj.host }} {% comment %}{% errors.host[0][0] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %} <span>{% error_message errors.host %}</span> </p> <p>端口: {{ obj.port }}<span>{{ errors.port }}</span></p> <p>邮箱: {{ obj.email }}<span>{{ errors.email }}</span></p> <p>手机: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p> <p>备注: {{ obj.memo }}<span>{{ errors.mome }}</span></p> <input type="submit" value="submit" /> </form> </body> </html>
user_list.html
具体实现可以参考:
下面介绍Ajax:
Ajax发送简单数据类型
可以将数据保存之后发送到后台,后台更新就可以了;
1、导入jQuery
{% load form_tag %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %} background-color: red; } </style> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} <p>用户类型: {{ obj.user_type }} <span>{% error_message errors.user_type %}</span> </p> <p>主机: {{ obj.host }} {% comment %}{% errors.host[0][0] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %} <span>{% error_message errors.host %}</span> </p> <p>端口: {{ obj.port }}<span>{{ errors.port }}</span></p> <p>邮箱: {{ obj.email }}<span>{{ errors.email }}</span></p> <p>手机: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p> <p>备注: {{ obj.memo }}<span>{{ errors.mome }}</span></p> <input type="submit" value="submit" /> </form> <input type="button" onclick="AjaxSumbit();" value="Ajax提交" /> <table border="1"> <thead> <tr> <th>主机名</th> <th>端口</th> </tr> </thead> <tbody id="tbd"> <tr> <th>1.1.1.1</th> <th>9999</th> </tr> <tr> <th>1.1.1.1</th> <th>9998</th> </tr> </tbody> </table> <script src="/static/jquery-1.8.2.min.js"></script> <script> function AjaxSumbit(){ var host=‘1.1.1.1‘; var port=‘9999‘; $.ajax({ ‘url‘:"/ajax_data/", type:"POST", data:{h:host,p:port}, success:function(arg){ } }) } </script> </body> </html>
user_list.html
2、views增加如下内容:
from django.shortcuts import HttpResponse def ajax_data(request): print request.POST return HttpResponse("ok")
3、urls内容:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^user_list/$‘, views.user_list), url(r‘^ajax_data/$‘, views.ajax_data), ]
urls
提交的数据内容如下:为字典类型
Ajax发送复杂数据类型(数组、字典)1、user_list.html
{% load form_tag %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %} background-color: red; } </style> </head> <body> <form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %} <p>用户类型: {{ obj.user_type }} <span>{% error_message errors.user_type %}</span> </p> <p>主机: {{ obj.host }} {% comment %}{% errors.host[0][0] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %} <span>{% error_message errors.host %}</span> </p> <p>端口: {{ obj.port }}<span>{{ errors.port }}</span></p> <p>邮箱: {{ obj.email }}<span>{{ errors.email }}</span></p> <p>手机: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p> <p>备注: {{ obj.memo }}<span>{{ errors.mome }}</span></p> <input type="submit" value="submit" /> </form> <input type="button" onclick="AjaxSumbit();" value="Ajax提交" /> <input type="button" onclick="AjaxSubmitSet();" value="Ajax提交集合" /> <table border="1"> <thead> <tr> <th>主机名</th> <th>端口</th> </tr> </thead> <tbody id="tbd"> <tr> <th>1.1.1.1</th> <th>9999</th> </tr> <tr> <th>1.1.1.1</th> <th>9998</th> </tr> </tbody> </table> <script src="/static/jquery-1.8.2.min.js"></script> <script> function AjaxSumbit(){ var host=‘1.1.1.1‘; var port=‘9999‘; $.ajax({ ‘url‘:"/ajax_data/", type:"POST", data:{h:host,p:port}, success:function(arg){ } }) } function AjaxSubmitSet(){ #传送字典 var array_users=[ {‘username‘:‘alex‘,‘age‘:18}, {‘username‘:‘Chales‘,‘age‘:17}, {‘username‘:‘eric‘,‘age‘:16} ]; $.ajax({ url:"/ajax_data_set/", type:‘POST‘, data:{data:array_users}, success:function(arg){ } }) } </script> </body> </html>
2、views
def ajax_data_set(request): print request.POST return HttpResponse("ok")
views
3、urls
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^user_list/$‘, views.user_list), url(r‘^ajax_data/$‘, views.ajax_data), url(r‘^ajax_data_set/$‘, views.ajax_data_set), ]
urls
但是上述提交的内容,不是原生的字符串,不是我们想要的,看下面:在原来的基础上添加内容:
function AjaxSubmitSet(){ var array_users=[ {‘username‘:‘alex‘,‘age‘:18}, {‘username‘:‘Chales‘,‘age‘:17}, {‘username‘:‘eric‘,‘age‘:16} ]; $.ajax({ url:"/ajax_data_set/", type:‘POST‘, tradition: true, data:{data:JSON.stringify(array_users)}, #将上面的字典转换为原生的字符串 success:function(arg){ } }) }
user_list.html
好,ajax简单数据和复杂数据的提交完成了,下面开始在后台进行更新;1、views
def ajax_data_set(request): ret = {‘status‘:True,‘error‘:""} #将这个结果返回到前端,来查看操作是否正常 try: print request.POST except Exception,e: ret[‘status‘] = False ret[‘error‘] = str(e) return HttpResponse(json.dumps(ret)) #成功的话,返回成功,失败,返回错误信息
2、user_list.html
function AjaxSubmitSet(){ var array_users=[ {‘username‘:‘alex‘,‘age‘:18}, {‘username‘:‘Chales‘,‘age‘:17}, {‘username‘:‘eric‘,‘age‘:16} ]; $.ajax({ url:"/ajax_data_set/", type:‘POST‘, tradition: true, data:{data:JSON.stringify(array_users)}, success:function(arg){ var callback_dict = $.parseJSON(arg); //将字符串转换为对象,类似于json.loads if (callback_dict.status){ alert(‘成功‘) }else { alert(callback_dict.error); } } }) }
user_list.html
作业: 1、登录页面,Form验证,session,登录成功跳转到index redirect跳转 2、默认访问index,点击登录跳回登录页面 3、列表页面 内容通过model去数据库中获取 model.assert.object.all()绑定到页面上; 4、添加页面(From表单,需要显示不合法的信息),添加之后,列表页面增加一条数据; 5、对列表页面数据的修改; 使用之前的进入编辑模式,退出编辑模式; 具体实现如下: 使用jQuery,循环所有的数据(表格),点击保存的时候,自动退出编辑模式,将数据放到一个数组中;array_list = [{‘hostname‘:xxx‘},‘hostname‘:xxx‘];, 使用$.ajax(),将每一条数据发送到后台更新,ajax发送成功之后,表示后台数据已经更新完成,使用window.location.href=window.location.href将页面刷新一次,就OK啦;
作业
#!/usr/bin/env python # _*_ coding:utf-8 _*_ from django import forms class LoginForm(forms.Form): username = forms.CharField( widget=forms.widgets.TextInput(attrs={‘class‘: "form-control","placeholder":"用户名"}) ) password = forms.CharField( widget=forms.widgets.PasswordInput(attrs={‘class‘: "form-control","placeholder":"密码"}) )
forms
"""s11day18_homework URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.9/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r‘^$‘, views.home, name=‘home‘) Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r‘^$‘, Home.as_view(), name=‘home‘) Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r‘^blog/‘, include(‘blog.urls‘)) """ from django.conf.urls import url,include from django.contrib import admin from cmdb import views urlpatterns = [ url(r‘^login/‘, views.login), url(r‘^index/‘, views.index), url(r‘^lists/‘, views.lists), url(r‘^add/‘, views.add), ]
cmdb\urls
#!/usr/bin/env python #coding:utf-8 from django.shortcuts import render from cmdb import forms # Create your views here. def login(request): obj = forms.LoginForm() #如果登录成功,写入session,跳转到index页面(home) return render(request,‘account/login.html‘,{‘model‘:obj}) def index(request): return render(request,‘home/index.html‘) def lists(request): return render(request,‘asset/lists.html‘) def add(request): return render(request,‘asset/import_single.html‘)
cmdb/views
主页:
显示列表:
添加页面: