框架,即framework,特指为解决一个开放性问题而设计的具备必定约束性的支撑结构,使用框架能够帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来作表演。css
web应用 访问请求流程html
*浏览器发送一个HTTP请求;
*服务器收到请求,生成一个HTML文档(待补充;是不是所有类型的访问都须要生成文档);
*服务器把HTML文档做为HTTP响应的Body发送给浏览器;
*浏览器收到HTTP响应,从HTTP Body取出HTML文档并解析显示
对于全部的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。(即BS架构)前端
静态页面--最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。python
若是要动态生成HTML,就须要把上述步骤本身来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,若是咱们本身来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。正确的作法是底层代码由专门的服务器软件实现,咱们用Python专一于生成HTML文档。由于咱们不但愿接触到TCP链接、HTTP原始请求和响应格式,因此,须要一个统一的接口,让咱们专心用Python编写Web业务。mysql
这个接口就是WSGI:Web Server Gateway Interface。
jquery
WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。自从 WSGI 被开发出来之后,许多其它语言中也出现了相似接口。nginx
WSGI 是做为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的,以提高可移植 Web 应用开发的共同点。WSGI 是基于现存的 CGI 标准而设计的。web
不少框架都自带了 WSGI server ,好比 Flask,webpy,Django、CherryPy等等。固然性能都很差,自带的 web server 更多的是测试用途,发布时则使用生产环境的 WSGI server或者是联合 nginx 作 uwsgi。ajax
通俗来说,WSGI就像是一座桥梁,一边连着web服务器,另外一边连着用户的应用。可是呢,这个桥的功能很弱,有时候还须要别的桥来帮忙才能进行处理。sql
WSGI有两方:“服务器”或“网关”一方,以及“应用程序”或“应用框架”一方。服务方调用应用方,提供环境信息,以及一个回调函数(提供给应用程序用来将消息头传递给服务器方),并接收Web内容做为返回值。
所谓的 WSGI中间件同时实现了API的两方,所以能够在WSGI服务和WSGI应用之间起调解做用:从WSGI服务器的角度来讲,中间件扮演应用程序,而从应用程序的角度来讲,中间件扮演服务器。“中间件”组件能够执行如下功能:
WSGI 的设计确实参考了 Java 的 servlet。http://www.python.org/dev/peps/pep-0333/ 有这么一段话:
By contrast, although Java has just as many web application frameworks available, Java’s “servlet” API makes it possible for applications written with any Java web application framework to run in any web server that supports the servlet API.
另外,须要说起的一点是:其它基于python的web框架,如tornado、flask、webpy都是在这个范围内进行增删裁剪的。例如tornado用的是本身的异步非阻塞“wsgi”,flask则只提供了最精简和基本的框架。Django则是直接使用了WSGI,并实现了大部分功能。
WSGI实例一 # -*- coding: utf-8 -*- from wsgiref.simple_server import make_server def application(environ, start_response): start_response('200 OK',[('Content-Type','text/html')]) return[b'<h1 >Hello, web!</h1>'] #''中间为空,表示的是本地地址 httpd = make_server('',8080, application) print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()</pre>
'''
1.整个application()函数自己没有涉及到任何解析HTTP的部分,也就是说,底层代码不须要咱们本身编写,
咱们只负责在更高层次上考虑如何响应请求就能够了。
2.application()函数必须由WSGI服务器来调用。有不少符合WSGI规范的服务器,咱们能够挑选一个来用。
3.Python内置了一个WSGI服务器,这个模块叫wsgiref
4.application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
//environ:一个包含全部HTTP请求信息的dict对象; //start_response:一个发送HTTP响应的函数。
5.在application()函数中,调用:start_response('200 OK',[('Content-Type','text/html')])
就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每一个
Header用一个包含两个str的tuple表示。
6.一般状况下,都应该把Content-Type头发送给浏览器。其余不少经常使用的HTTP Header也应该发送。
而后,函数的返回值b'<h1>Hello, web!</h1>'将做为HTTP响应的Body发送给浏览器。
7.有了WSGI,咱们关心的就是如何从environ这个dict对象拿到HTTP请求信息,而后构造HTML,经过
start_response()发送Header,最后返回Body。
'''
WSGI实例二 from wsgiref.simple_server import make_server def f1(): f1=open("jd_index1.html","rb") data1=f1.read() return[data1] def f2(): f2=open("tb_index.html","rb") data2=f2.read() return[data2] def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK',[('Content-Type','text/html')]) # 若是URL路径为京东,执行函数1,返回京东主页 if path=="/jingdong": return f1() # 若是URL路径为淘宝,执行函数2,返回淘宝主页 elif path=="/taobao": return f2() else: return["<h1>404</h1>".encode("utf8")] httpd = make_server('',8810, application) print('Serving HTTP on port 8810...') # 开始监听HTTP请求: httpd.serve_forever() 打开浏览器访问相应的路径 这里咱们WSGI每次修改完数据后,都须要从新启动该服务。
WSGI实例3 打印当前时间 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2016/11/24 # @Author : Jesson import time from wsgiref.simple_server import make_server def f1(req): print(req) print(req["QUERY_STRING"]) f1=open("jd_index1.html","rb") data1=f1.read() return[data1] def f2(req): f2=open("tb_index.html","rb") data2=f2.read() return[data2] def f3(req):#模版以及数据库 f3=open("current_time.html","rb") data3=f3.read() times=time.strftime("%Y-%m-%d %X", time.localtime()) # 在前端相应的页面 设置自定义模版语言'! !' data3=str(data3,"utf8").replace("!time!",str(times)) return[data3.encode("utf8")] def routers(): urlpatterns =( ('/jingdong',f1), ('/taobao',f2), ("/cur_time",f3) ) return urlpatterns def application(environ, start_response): print(environ['PATH_INFO']) path=environ['PATH_INFO'] start_response('200 OK',[('Content-Type','text/html')]) urlpatterns = routers() func =None for item in urlpatterns: if item[0]== path: func = item[1] break if func: return func(environ) else: return["<h1>404</h1>".encode("utf8")] httpd = make_server('',8828, application) print('Serving HTTP on port 8828...') # 开始监听HTTP请求: httpd.serve_forever()
MVC百度百科:全名Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑汇集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不须要从新编写业务逻辑。
通俗解释:一种文件的组织和管理形式!不要被缩写吓到了,这其实就是把不一样类型的文件放到不一样的目录下的一种方法,而后取了个高大上的名字。固然,它带来的好处有不少,好比先后端分离,松耦合等等,就不详细说明了。
模型(model):定义数据库相关的内容,通常放在models.py文件中。
视图(view):定义HTML等静态网页文件相关,也就是那些html、css、js等前端的东西。
控制器(controller):定义业务逻辑相关,就是你的主要代码。
MTV: 有些WEB框架以为MVC的字面意思很别扭,就给它改了一下。view再也不是HTML相关,而是主业务逻辑了,至关于控制器。html被放在Templates中,称做模板,因而MVC就变成了MTV。这其实就是一个文字游戏,和MVC本质上是同样的,换了个名字和叫法而已,换汤不换药。
在web开发的项目文件中,相关目录分开存放,必需要有机制将他们在内里进行耦合。在Django中,urls、orm、static、settings等起着重要的做用。
1. 目录结构规范
2. urls路由方式
3. settings配置
4. ORM操做
5. 模板渲染
6. 其它
安装: pip3 install django
建立project工程:django-admin startproject mysite
建立APP应用:python mannage.py startapp app01
settings配置:TEMPLATES
STATICFILES_DIRS=(os.path.join(BASE_DIR,"statics"),) #必定要加逗号
# 咱们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找
根据需求设计代码:url.py view.py
模版引擎:templates
链接数据库,操做数据:model.py
django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每个Django Project里都会有一个mannage.py。
manage.py —– Django项目里面的工具,经过它能够调用django shell和数据库等。
settings.py —- 包含了项目的默认设置,包括数据库信息,调试标志以及其余一些工做的变量。
urls.py —– 负责把URL模式映射到应用程序。
在mysite目录下建立app01应用: python manage.py startapp app01
启动django项目:python manage.py runserver 8080
生成同步数据库的脚本文件:python manage.py makemigrations
同步数据库: python manage.py migrate
注意:
在开发过程当中,数据库同步误操做以后,不免会遇到后面不能同步成功的状况,解决这个问题的一个简单粗暴方法是把migrations目录下的脚本(除__init__.py以外)所有删掉,再把数据库删掉以后建立一个新的数据库,数据库同步操做再从新作一遍。
当咱们访问http://127.0.0.1:8080/admin/时,会出现:
因此咱们须要为进入这个项目的后台建立超级管理员:python manage.py createsuperuser 终端执行上述命令,设置好用户名和密码后即可登陆啦!
设置用户名的时候,邮箱email能够不用输入,密码有复杂度校验,设置的复杂点。
另外,还会提示你,密码会明文显示。
清空数据库:** python manage.py flush**
如何更改正在运行的开发服务器端口
#进入django命令行,执行:
python manage.py runserver 加上新的端口号8080
1.单一路由对应
1
|
url(r
'^index$'
, views.index),
|
二、基于正则的路由
1
2
|
url(r
'^index/(\d*)'
, views.index),
url(r
'^manage/(?P<name>\w*)/(?P<id>\d*)'
, views.manage),
|
三、添加额外的参数
1
|
url(r
'^manage/(?P<name>\w*)'
, views.manage,{
'id'
:
333
}),
|
四、为路由映射设置名称
1
2
|
url(r
'^home'
, views.home, name
=
'h1'
),
url(r
'^index/(\d*)'
, views.index, name
=
'h2'
),
|
设置名称以后,能够在不一样的地方调用,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
caption
=
models.CharField(max_length
=
16
)
def
get_absolute_url(
self
):
"""
为每一个对象生成一个URL
应用:在对象列表中生成查看详细的URL,使用此方法便可!!!
:return:
"""
# return '/%s/%s' % (self._meta.db_table, self.id)
# 或
from
django.urls
import
reverse
return
reverse(
'NewType.Detail'
, kwargs
=
{
'nid'
:
self
.
id
})
|
获取请求匹配成功的URL信息:request.resolver_match
五、路由分发
1
|
url(r
'^web/'
,include(
'web.urls'
)),
|
$.ajax({ url:'/csrf1.html', #指定路径 type:'POST', #什么方式发送,get,post,put,delete headers:{'X-CSRFToken':token}, #请求头也能够放东西 data:{'user':user}, #请求体传的的东西 dataType:'JSON', #接收来自服务端的json字符串自动解成字符串 traditional:true, #串列表或元组的时候用 success:function (arg) { #会调函数,参数是服务端返回的字符串 console.log(arg); } })
js阻止默认事件的发生:onclick='return func();' function down(){return false;}
jQuery事件阻止默认事件发生:$('#addModal').click(function(){return false;})
请求头 -> 提取URL -> 路由关系匹配 -> 函数 (模板+数据渲染) -> 返回用户(响应头+响应体)
重定向是服务端给客户端发送一个重定向命令,而后客户端在链接到新的地址,重定向是有服务端发起,浏览器完成
模板渲染也是有服务端模板和要返回给客户的内容结合后的新的字符串发送给浏览器,浏览器识别并显示出来
layout.html
{% block x %}{% endblock %}
{% extends 'layout' %}
{% block x %}.......{% endblock %}
在浏览器上保持的键值对,参数(超时时间,域名)
服务器写Cookie:
#obj=HttpReponse(...)
#obj=render(...)
obj=redirect(...) #不必定是redirect三个中的任意一个都行
obj.set_cookie(k1,v1,max_age) #max_age超时时间,过了这个时间就消失了
obj.set_signed_cookie(k1,v1,max_age,salt='fff') #加盐版
获取Cookie:
request.COOKIES.get('k1')
request.get_signed_cookie('k1'.salt='fff') #接收加盐版Cookie
Cookie做用登陆和限制操做次数(投票)
须要修改的地方: 1.将MySQLdb修改成pymysql 2.把SQLlite改成mysql 步骤: 1.建立数据库 2.DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'db6', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': 3306, } } 3.import pymysql pymysql.install_as_MySQLdb() 4.在models中建立: class UserInfo(models.Model): nid=models.BigAutoField(primary_key=True) username=models.CharField(max_length=32) password=models.CharField(max_length=64) 5.注册app01 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01' ] 6.建立数据表 Python manage.py makemigrations python manage.py migrate 7.class UserGroup(models.Model): ''' 部门 ''' title=models.CharField(max_length=32) class UserInfo(models.Model): ''' 员工 ''' nid=models.BigAutoField(primary_key=True) #AutoField 自动字段,这里是自增字段至关于自增int类型 user=models.CharField(max_length=32) password=models.CharField(max_length=64) # age=models.IntegerField(null=True) age=models.IntegerField(default=1) ug=models.ForeignKey("UserGroup",null=True)
8.连表正反向操做
#两张表userinfo(含外键列ut_id)和usertype
#对象正向操做: ut.(usertype列名)
#对象反向操做:userinfo_set.(userinfo列名)
value正向操做:ut__(usertype列名)
value反向操做:userinfo__(userinfo列名)
九、更多操作
http://www.cnblogs.com/wupeiqi/articles/6216618.html
1九、CSRF
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/csrf1.html" method="POST"> //方式一*********************************************** {# {% csrf_token %}#} <input type="text" name="user" id="user"> <input type="submit" value="提交"> <button onclick="submitForm()">Ajax提交</button> </form> </body> <script src="/static/jquery-3.2.1.js"></script> <script src="/static/jquery.cookie.js"></script> <script> //方式二*********************************************** {# function submitForm() {#} {# var csrf = $('input[name="csrfmiddlewaretoken"]').val();#} {# var user = $('#user').val();#} {# $.ajax({#} {# url:'/csrf1.html',#} {# type:'POST',#} {# data:{'user':user,'csrfmiddlewaretoken':csrf},#} {# success:function (arg) {#} {# console.log(arg);#} {# }#} {# })#} {# }#} //方式三*********************************************** function submitForm() { var token=$.cookie('csrftoken'); var user=$('#user').val(); $.ajax({ url:'/csrf1.html', type:'POST', headers:{'X-CSRFToken':token}, data:{'user':user}, dataType:'JSON', traditional:true, success:function (arg) { console.log(arg); } }) } //方式四************************************************ function submitForm(){ $.ajax({ url:'/csrf1.html', type:'POST', data:{'user':user,'csrfmiddlewaretoken':"{{csrf_token}}"} dataType:'JSON', traditional:true, success:function (arg) { consol.log(arg); } }) } </script> </html> 1. CSRF a. 基本应用 form表单中添加 {% csrf_token %} b. 全站禁用 # 'django.middleware.csrf.CsrfViewMiddleware', c. 局部禁用 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt @csrf_exempt def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok') d. 局部使用 # 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok') c. 特殊CBV from django.views import View from django.utils.decorators import method_decorator @method_decorator(csrf_protect,name='dispatch') class Foo(View): def get(self,request): pass def post(self,request): pass PS:CBV中添加装饰器 def wrapper(func): def inner(*args,**kwargs): return func(*args,**kwargs) return inner # 1. 指定方法上添加装饰器 # class Foo(View): # # @method_decorator(wrapper) # def get(self,request): # pass # # def post(self,request): # pass # 2. 在类上添加 # @method_decorator(wrapper,name='dispatch') # class Foo(View): # # def get(self,request): # pass # # def post(self,request): # pass Ajax提交数据时候,携带CSRF: a. 放置在data中携带 <form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="user" type="text" name="user" /> <input type="submit" value="提交"/> <a onclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function submitForm(){ var csrf = $('input[name="csrfmiddlewaretoken"]').val(); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', data: { "user":user,'csrfmiddlewaretoken': csrf}, success:function(arg){ console.log(arg); } }) } </script> b. 放在请求头中 <form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="user" type="text" name="user" /> <input type="submit" value="提交"/> <a onclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> function submitForm(){ var token = $.cookie('csrftoken'); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', headers:{'X-CSRFToken': token}, data: { "user":user}, success:function(arg){ console.log(arg); } }) } </script>
导入小组件 pub.html <div> <h3>特别漂亮的组件</h3> <div class="title">标题:{{ name }}</div> <div class="content">内容:{{ name }}</div> </div> ********************************************************************* test.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> {% include 'pub.html' %} {% include 'pub.html' %} {% include 'pub.html' %} </body> </html>
函数-> 自动执行 模板自定义函数: - simple_filter - 最多两个参数,方式: {{第一个参数|函数名称:"第二个参数"}} - 能够作条件判断 - simple_tag - 无限制: {% 函数名 参数 参数%}
定义:保存在服务端的数据(本质是键值对)
应用:依赖cookie
做用:保持会话(Web网站)
好处:敏感信息不会直接给客户端
class UInfo(models.Model): nickname=models.CharField(max_length=32) username=models.CharField(max_length=32) password=models.CharField(max_length=64) gender_choices=[ (1,'男'), (2,'女'), ] gender=models.IntegerField(choices=gender_choices) m=models.ManyToManyField('UInfo') ''' Reverse accessor for 'U2U.b' clashes with reverse accessor for 'U2U.g'. 'UInfo.b'的反向访问器与“UInfo.g”的反向访问器冲突, obj(对象男).U2U_set.all()与obj(对象女).U2U_set.all()同样产生冲突 related_qury_name:[a,b] obj(对象男).a_set.all() obj(对象女).b_set.all() related_name:[a,b] obj(对象男).a.all() obj(对象女).b.all() ''' # class U2U(models.Model): # g=models.ForeignKey('UInfo',related_name='boys') # b=models.ForeignKey('UInfo',related_name='girls') class Comment(models.Model): new_id=models.IntegerField() #新闻ID content=models.CharField(max_length=32) #评论内容 user=models.CharField(max_length=32) #评论者 reply=models.ForeignKey('Comment',null=True,blank=True)
def test2(request): #多对多两张表自关联 # #主流方式一,传id # models.U2U.objects.create(b_id=1,g_id=4) # models.U2U.objects.create(b_id=1,g_id=5) # models.U2U.objects.create(b_id=1,g_id=6) # models.U2U.objects.create(b_id=2,g_id=5) # models.U2U.objects.create(b_id=3,g_id=6) # #主流方式二,传对象 # boy=models.UInfo.objects.filter(gender=1,id=2).first() # girl=models.UInfo.objects.first(gender=2,id=6).first() # models.U2U.objects.create(b=boy,g=girl) # #虽然穿的是对象可是其内部本质也是取的id # xz=models.UInfo.objects.filter(id=1).first() # ret=xz.girls.all() #和xz对象(行)有关系的U2U表中的全部对象(行) # print(ret) # for u in ret: # print(u.g.nickname) #从U2U跨表到UInfo #多对多ManyToMany自关联,from属于正向操做,to属于反向操做 #from正向操做 # xz=models.UInfo.objects.filter(id=1).first() # objs=xz.m.all() # # print(objs) # for obj in objs: # print(obj.nickname) #to反向操做 # mr=models.UInfo.objects.filter(id=4).first() # print(mr.nickname) # v=mr.uinfo_set.all() # for row in v: # print(row.nickname) #FK自关联 # obj=models.Comment.objects.filter(id=4).first() #对象(第四行) # print(obj.reply) #对象(与第四行相关联的那行) return HttpResponse('...')