travel for django
参考博客:http://www.cnblogs.com/wupeiqi/articles/5237672.html
一:框架的本质:
最原始的框架:服务端一个简单的socket,接收客户端发出的请求,服务端调用相应的函数处理用户的请求,并把请求返回用户。
code:
1 import socket 2 S=socket.socket() 3 IP_port=('0.0.0.0',8000) 4 S.bind(IP_port) 5 S.listen(5) 6 7 def handle(con): 8 # con.send(bytes("HTTP/1.1 200 OK\r\n\r\n",encoding='utf-8')) 9 con.send(bytes('welcome to evil_liu blog',encoding='utf-8')) 10 11 12 if __name__ == '__main__': 13 while True: 14 con,info= S.accept() 15 handle(con)
- 上面的简单的服务器代码,就是接收请求,处理请求。这个是web框架的雏形。
- 随着时间推移,推出一个wsgi标准,一个定义web底层socket封装的标准。
- WSGI 没有官方的实现, 因为WSGI更像一个协议. 只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。
- 一个web开发包含两部分:服务器程序和应用程序。服务器程序负责对sokcet的服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序负责具体的逻辑处理。
- 为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不 同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用 使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定, 双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。 WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。
python标准库提供了:wscgiref服务器接口。在python2版本运行。3报一些错。
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 from wsgiref.simple_server import make_server 5 6 def RunServer(environ, start_response): 7 start_response('200 OK', [('Content-Type', 'text/html')]) 8 return '<h1>Hello, web!</h1>' 9 10 if __name__ == '__main__': 11 httpd = make_server('', 8000, RunServer) 12 print("Serving HTTP on port 8000...") 13 httpd.serve_forever()
Django框架流程:
一:创建一个项目:
安装django:pin install django
命令行:django-admin.exe startproject mysite
或者直接pycharm中进行手动创建。
目录结构:
mysite
mysite
-settings.py#配置文件。
-urls.py#路由系统
-wsgis.py#WSGI 无需关注。
manager.py :django程序启动文件。
二:创建app。一个project可以创建多个app。多个app共享project配置。
创建:python manager.py startapp appname
目录介绍:
admin.py:web版本后台管理。稍作配置,就可以创建一个后台程序。
models.py:数据库相关操作。包括创建等。
views.py:业务请求逻辑处理。
app.py:当前app配置文件。
test.py:单元测试。测试具体功能。
三:编写代码。
分别编写urls.py写路由规则。
在views.py写对应的请求处理函数。
注意:
在views.py写请求函数的时候,函数需要携带一个参数,默认我们写request 当然可以写其他的代替,该参数是携带用户请求的信息。必须有的参数。
当我们想返回字符串的时候,不是直接return 字符串,给浏览器,需要我们用Httprespone(‘string’) 进行浏览器的返回。
四:启动:
命令行:python manage.py runserver 127.0.0.1:8888
或者pycharm中运行:
编辑:
然后点击:
运行。
客户端进行访问:
http://127.0.0.1:8000/index/
五:使用模板。
1)需要在setting.py文件配置。
2)在views.py进行调用。
首先jango本身不知道引用模板的去哪里找。在setting.py文件中有相应的配置进行配置。
有具体的配置在这里。所以我们的模板文件是放在templates目录中。这样当我们引用这个html模板文件的时候,jango会到这个目录下找该文件。
views.py文件进行调用。
1:之前我们给客户端浏览器返回的是字符串,需要在给django传Httprespones(‘string’)对象,
2:而返回给客户端浏览器html文件需要render()函数给django传入。
render函数需要django模块导入。
1 from django.shortcuts import render
render方法需要传入2个参数。一个request记录客户端请求信息的参数。一个是html文件的名字。
完整:
1 from django.shortcuts import render 2 from django.shortcuts import HttpResponse 3 4 # Create your views here. 5 def index(reuqest): 6 return render(reuqest,'index.html') 7 def regis(request): 8 return render(request,'demo.html') 9 def respon(): 10 return HttpResponse('OK')
render函数的返回结果也可以给html文件返回变量,以便在html文件中进行变量引用。变量可以正常变量也可以是报错信息。
1 return render(request,'registe.html',{'error':'用户名重复!'})
1 def login(request): 2 ''' 3 功能:该函数主要功能是用户登录页面以及后台用户账号密码验证。 4 :param x: 储存用户请求信息。 5 :return: get请求返回登录页面,post请求如果验证正确返回后台页面,验证失败返回错误提示。 6 ''' 7 if (request.method=="POST"): 8 user=request.POST.get('username',None) 9 pwd=request.POST.get('password',None) 10 user_obj=Userinfo.objects.all() 11 # Userinfo.objects.filter(user='ccccc').delete() 12 for i in user_obj: 13 print(i.id,i.user) 14 user_list=[i.user for i in user_obj] 15 if user in user_list and user_obj[user_list.index(user)].password==pwd: 16 result=request.session.get('IS_LOGIN',None) 17 print(result) 18 request.session['IS_LOGIN']=True 19 return redirect('/home/') 20 else: 21 return render(request, 'login.html', {'error': '用户或者密码错误'}) 22 return render(request, 'login.html')
如上代码,当我们get请求的时候,变量error是空值,在html文件中的代码:
1 <form action="/index/" method="post"> 2 <input type="text" name="username" class="username" onfocus="App(this)" placeholder="用户名"> 3 <input type="password" name="password" class="password" onfocus="App(this)" placeholder="密码"> 4 <div class="error"><span>+</span></div> 5 <div class="mis"><span>{{ error}}</span></div> 6 <button type="submit">登陆</button> 7 </form>
空值的时候,登录页面没有错误信息显示。当我们进行POST验证的时候,后台进行数据验证时候,如果验证账号密码错误。error值为错误信息:用户或者密码错误。登录页面显示错误。
当我们返回字符串的时候:需要用Httprespones(string)进行返回。
3:如果客户端符合某种验证条件的时候,对页面跳转redirect(‘url’):
1 return redirect('/home/')
六:引用静态文件:js css image等。
因为django 本身不知道改去哪引用静态文件。需要在setting.py文件中进行设置。
加入:
1 STATICFILES_DIRS = ( 2 os.path.join(BASE_DIR,'static'), 3 )
注意在元组内的最后元素需要用逗号(,)否则会报错。
详细配置:
1 STATIC_URL = '/static/' 2 STATICFILES_DIRS = ( 3 os.path.join(BASE_DIR,'static'), 4 )
其中:STATIC_URL是请求后缀,可以随便进行写。需要注意的是:在你html进行引用相应的静态文件的时候,一定要和这个值匹配,否则django找不到,可以理解成:客户端浏览器请求资源定位符。
必须要和STATIC_URL的值保持一致。
STATIC_URL = '/a/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) <script src="/a/js/scripts.js"></script>
数据提交:
form表单的提交。 其中/index/表示提交后台那个url。即ulrs.py中对应的。
1 url(r'^index/', views.index),
1 <form action="/index/" method="post">#注意action的地址相对url。和urls.py对应。
然后通过对应的函数:views.index函数获取用户的提交内容。如果不是post请求,直接返回用户请求html文件。
1 def index(x): 2 if (x.method=="POST"):#对用户请求的方法进行判断。 3 user=x.POST.get('username')#获取提交中的username的值。 4 pwd=x.POST.get('password')#获取提交中的password的值。 5 print(user,pwd)#打印屏幕输出。 6 return render(x,'index.html')
在form表单提交的时候出现:
这是我们模拟跨站请求的时候报错。需要注释setting中
效果:
八:创建数据库:
创建数据库:
命令行:
1 python manage.py makemigrations 2 python manage.py migrate
数据库配置文件为:models.py:数据库相关操作。包括创建等。和sqlalchemy一样,创建数据库也需要继承一个类:models.Model。
1 class Userinfo(models.Model): 2 ''' 3 功能:该类主要功能是创建用户的信息表格。 4 ''' 5 user=models.CharField(max_length=12) 6 password=models.CharField(max_length=40) 7 ipone_num=models.CharField(max_length=12) 8 9 10 class Hostinfo(models.Model): 11 ''' 12 功能:该类为用户录入主机数据表格。 13 ''' 14 host=models.CharField(max_length=32) 15 ip=models.CharField(max_length=34) 16 stat=models.CharField(max_length=32) 17 prot=models.CharField(max_length=32)
注册APP:setting里设置:否则无法创建数据库。
django默认数据库:
默认情况,数据库会帮你创建一个id自增列,做为主键。
查询:
1 user_obj=Userinfo.objects.all()#查询所有数据。
查询出来的是对象的集合 和sqlalchemy一样。需要循环取(user_obj.host)值。
如果条件查询:
1 item=Hostinfo.objects.filter(id=val)
增加:
1 Hostinfo.objects.create(host=host[0],ip=ip[0],stat=stat[0],prot=port[0])
更新:
1 Hostinfo.objects.filter(id=val).update(host=host[index])
删除:
1 Hostinfo.objects.filter(id=1).delete()
九:模板引擎。
python和html交互通过模板引擎来实现。比如python的变量通过render方法传递给html,然后用模板语言在html进行引用:
1 def home(request): 2 ''' 3 功能:该函数主要功能是后台管理页面。 4 :param request: 5 :return:根据用户登录状态来判断返回,登录返回后台页面。未登录返回登录页面。 6 ''' 7 is_login=request.session.get('IS_LOGIN',False) 8 host_obj=Hostinfo.objects.all() 9 if is_login: 10 # host_obj=Hostinfo.objects.all() 11 if request.method=='POST': 12 id=request.POST.getlist('id',None) 13 host=request.POST.getlist('hostname',None) 14 ip=request.POST.getlist('IP',None) 15 stat=request.POST.getlist('status',None) 16 port=request.POST.getlist('port',None) 17 if not id: 18 print('first') 19 print(host,ip,host,stat) 20 Hostinfo.objects.filter(id=1).delete() 21 Hostinfo.objects.create(host=host[0],ip=ip[0],stat=stat[0],prot=port[0]) 22 host_obj=Hostinfo.objects.all() 23 return render(request, 'home.html', {'data': host_obj}) 24 # elif not port and len(ip)!=0 and len(host)!=0 and len(stat) !=0 : 25 else: 26 print('second') 27 print(id,host,ip,stat) 28 for index,val in enumerate(id): 29 item=Hostinfo.objects.filter(id=val)#注意查询出来时列表的集合。 30 if item[0].ip != ip[index]: 31 Hostinfo.objects.filter(id=val).update(ip=ip[index]) 32 if item[0].host != host[index]: 33 Hostinfo.objects.filter(id=val).update(host=host[index]) 34 if item[0].stat != stat[index]: 35 Hostinfo.objects.filter(id=val).update(stat=stat[index]) 36 host_obj=Hostinfo.objects.all() 37 return render(request,'home.html',{'data':host_obj})#给html传递变量data 38 return render(request, 'home.html',{'data':host_obj}) 39 else: 40 return render(request,'login.html')
html里引用:
1 <form action="/home/" method="post"> 2 <table class="table" > 3 4 <thead> 5 <tr> 6 <th>choice</th> 7 <th>id</th> 8 <th>hostname</th> 9 <th>IP</th> 10 <th>port</th> 11 <th>status</th> 12 </tr> 13 </thead> 14 <tbody> 15 {% for item in data %} 16 <tr> 17 <td><input type="checkbox" onclick="mod(this);cancle(this)"/></td> 18 {# <td><input name="id" type="hidden" value={{item.id}}>{{item.id}}</td>#} 19 <td order="id" edit="true">{{item.id}}</td> 20 <td edit="true">{{item.host}}</td> 21 <td edit="true">{{item.ip}}</td> 22 <td>{{ item.prot }}</td> 23 <td edit="true">{{item.stat}}</td> 24 </tr> 25 {% endfor %} 26 </tbody> 27 </table> 28 <input type='submit' value="commit" /> 29 </form>
模板语言中的for循环需要结束符。{%endfor%}。变量引用使用2个大括号:{{变量}}
语法:
1 {%for i in xx%} 2 <样式> 3 {%enfor%}
小技巧:
- 在如果后端给前端模板出入的参数很多,如果我们定义字典的话,我们将会写很多的字段。我们可以用locals()内建函数来获取当前定义的局部变量。
前端显示的时候直接写变量既可。
1 def pub_date(request): 2 import time 3 pub_dat='2012-08-26 16:00:00' 4 a=2 5 print(pub_dat) 6 return render(request,'s1.html',locals())
模板语言:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 {{pub_dat}} 9 <div>{{ a }}</div> 10 </body> 11 </html>