框架,即framework,特指为解决一个开放性问题而设计的具备必定约束性的支撑结构,使用框架能够帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来作表演。html
对于全部的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。前端

1 import socket 2 3 def handle_request(client): 4 5 buf = client.recv(1024) 6 client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) 7 client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) 8 9 def main(): 10 11 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 12 sock.bind(('localhost',8001)) 13 sock.listen(5) 14 15 while True: 16 connection, address = sock.accept() 17 handle_request(connection) 18 connection.close() 19 20 if __name__ == '__main__': 21 22 main()
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。python
若是要动态生成HTML,就须要把上述步骤本身来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,若是咱们本身来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。jquery
正确的作法是底层代码由专门的服务器软件实现,咱们用Python专一于生成HTML文档。由于咱们不但愿接触到TCP链接、HTTP原始请求和响应格式,因此,须要一个统一的接口,让咱们专心用Python编写Web业务。web
在python中提供一个接口,帮咱们封装socket,即wsgiref模块:Web Server Gateway Interface。正则表达式
1 from wsgiref.simple_server import make_server 2 3 4 def RunServer(environ, start_response): 5 start_response('200 OK', [('Content-Type', 'text/html')]) 6 return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]#返回的内容 7 8 9 if __name__ == '__main__': 10 httpd = make_server('', 8000, RunServer) 11 print("Serving HTTP on port 8000...") 12 httpd.serve_forever()

整个application()函数自己没有涉及到任何解析HTTP的部分,也就是说,底层代码不须要咱们本身编写, 咱们只负责在更高层次上考虑如何响应请求就能够了。 application()函数必须由WSGI服务器来调用。有不少符合WSGI规范的服务器,咱们能够挑选一个来用。 Python内置了一个WSGI服务器,这个模块叫wsgiref application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数: //environ:一个包含全部HTTP请求信息的dict对象; //start_response:一个发送HTTP响应的函数。 在application()函数中,调用: start_response('200 OK', [('Content-Type', 'text/html')]) 就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。 start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每 个Header用一个包含两个str的tuple表示。 一般状况下,都应该把Content-Type头发送给浏览器。其余不少经常使用的HTTP Header也应该发送。 而后,函数的返回值b'<h1>Hello, web!</h1>'将做为HTTP响应的Body发送给浏览器。 有了WSGI,咱们关心的就是如何从environ这个dict对象拿到HTTP请求信息,而后构造HTML, 经过start_response()发送Header,最后返回Body。
只要有请求,就会触发RunServer函数,数据库
environ封装了客户端发来的全部数据,
start_response封装要返回给用户的数据,好比:响应头,状态等
如今咱们访问localhost:8000,显示出来的都是hello,web,通常的网站的url都会有什么/data,/index等,用来显示不一样的页面内容,那咱们应该怎么作呢?django
咱们设置断点,进入调试模式,在运行浏览器能够看到:浏览器
environ中有不少的参数,咱们找到一个叫作PATH_INFO的参数,那个就是显示咱们url后面有什么。缓存
这样咱们就可以经过url进行判断,而后进入相应的页面:
from wsgiref.simple_server import make_server def handle_index(): return [bytes('<h1>Hello, Index!</h1>', encoding='utf-8'), ] def hanle_date(): return [bytes('<h1>Hello, Date!</h1>', encoding='utf-8'), ] def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) currnet_url = environ['PATH_INFO']; if currnet_url =='/index': return handle_index() elif currnet_url =='/date': return hanle_date() else: return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ] if __name__ == '__main__': httpd = make_server('', 8000, RunServer) print("Serving HTTP on port 8000...") httpd.serve_forever()
经过这个咱们完成了一些基本的操做。
那若是说url不少,咱们不可能一个一个去判断吧,那咱们应该怎么作呢?python中几乎因此的web框架都是把全部的url放在一个列表中: 而后一类的url能够经过正则表达式进行匹配
URL_DICT = { "/index":handle_index, "/date":handle_date, } def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) currnet_url = environ['PATH_INFO']; func = None if currnet_url in URL_DICT: func = URL_DICT[currnet_url] if func: return func() else: return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ]
咱们看上面的代码,若是咱们把return里的html放在一个html文件中,并放在View文件夹中;把handle_index等处理业务逻辑的函数写在一个py文件中并放在Controller文件夹中。从数据库读取的方法放在Model文件夹中。
咱们须要html的时候就打开html文件f=open("html文件",mode="rb")而后read读取就能够了。
咱们须要用函数的时候就直接from Controller import 文件名,而后用文件名.函数名就能够了。
咱们在html中想要用一些特殊的符号,数据从数据库中获取替换,也只要引入model文件家中的方法,读出数据以后用replace函数替换符号和函数就能够了。
MVC:
Model数据库 View模板文件 Controller业务处理
MTV:(Django是基于MTV的框架)
Model数据库 Template模板文件 View业务处理
2、Django
2.一、安装Django
安装:pip install django;
安装完以后就多了一个可执行文件
2.二、建立django程序
方式一:经过命令行进入你要建立的目录下,而后输入命令 :django-admin.exe startproject mydjango
方式二:经过pycharm直接建立Django程序
2.2.一、工程目录
├── mysite
└── mysite #这个才是工程的包名。
├── __init__.py #代表mysite是一个包。 ├── settings.py #Django的配置文件,包括工程的app配置、数据库配置、语言配置等。 ├── urls.py #Django的调度者,根据不一样的url映射到不一样的视图。 └── wsgi.py #WSGI是web server gateway interface,这个文件是使project符合这种协议的入口点(entry-point 指令变换点) ├── manage.py #与Django进行交互的命令行工具,好比后面根据model生成数据库表结构、供开发使用的server等都是使用该工具,在manage.py的同级目录使用python manage.py 能够看到可使用的命令列表
2.3运行Django程序
方式一:进入程序目录下经过命令行运行
python manage.py runserver (127.0.0.1:8001),默认端口号为8000
方式二:在pycharm中运行
要注意要运行你的项目名称,而不是manage.py或者是其余的文件
若是要改运行的url和端口名:直接在host和port中设置就能够了
2.四、建立app
一个project能够又多个app,一个app能够同时属于多个project。经过如下命令建立一个app(在project目录下)
建立app: python manage.py startapp cmdb
2.4.一、app目录
. ├── manage.py ├── django_learn │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── cmdb # app的根目录 ├── admin.py #Django自带了一个管理界面,这个文件能够注册model在界面中管理 ├── apps.py #配置当前app ├── __init__.py #代表polls也是一个包 ├── migrations #用来初始化数据库,在执行python manage.py makemigrations 的时候会自动生成一个文件在这里 │ └── __init__.py #代表migrations也是一个包 ├── models.py #写指定的类,经过命令能够建立数据库结构 ├── tests.py #写测试代码 └── views.py #业务代码 Django映射urls.py里面的url的时候,在views.py里面查找对应的处理方法
3、练习--提交数据并展现(数据库)
需求:
1.首先在django_learn文件夹下面建立templates文件夹用于存放html文件。
若是在执行程序的时候,报找不到template的错误,那么是settings里面定义的路径的问题。
2.在配置文件urls.py中指定路由关系:
3.在cmdb这个app的view下定义用户的处理逻辑:
这里django中有render模块直接封装了文件的打开读取关闭的过程。传入的index.html的路径名是由django_learn下面的setting中的templates决定的(位置见1中ps):
4.导入静态文件
在mysite下面创建文件夹statics
在templates下的html文件里面添加引用
<script src="/static/jquery-1.12.4.js"></script>
在settings.py里面定义静态文件的路径
STATIC_URL = '/static/' #做用:若是下面的tatics名字变了,仍然能够用static来进行静态文件的路径拼接, # 此时<script src="/statics/jquery-1.12.4.js"></script> = <script src="/static/jquery-1.12.4.js"></script> #目的是防止路径变化致使前端人员引入静态文件的路径都得改,因此前端人员统一用/static进行拼接就好了 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'statics'), )
注意这里静态文件的URL要与src引入的路径相匹配,而后经过http://127.0.0.1:8000/statics/jquery-1.12.4.js访问JQuery成功。
5.咱们如今没有作数据处理,咱们点击提交:出现了CSRF的错误
若是咱们不想要这个错误的话能够把settings中的代码注释了:
再次输入127.0.0.1:8080/userInfo 就能够访问啦!!
6.上面表单的提交在页面刷新之后就没有了,由于内容是存放在缓存中的,如今,咱们须要将数据存放在数据库当中,改写以前的代码。
在models.py中建立userInfo的类:
class userinfo(models.Model): username=models.CharField(max_length=64) sex = models.CharField(max_length=64) email= models.CharField(max_length=64)
在settings.py中注册cmdb,而且查看DATABASES的设置:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cmdb', #必须先注册,不然下面会报错
]
执行命令建立数据库,表
D:\Python\mysite>python manage.py makemigrations Migrations for 'cmdb': cmdb\migrations\0001_initial.py: - Create model UserInfo D:\Python\mysite>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, cmdb, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying cmdb.0001_initial... OK Applying sessions.0001_initial... OK
在用户逻辑views.py中须要引入models操做数据库
from cmdb import models def userInfo(request): if request.method=="POST": u=request.POST.get("username",None) s=request.POST.get("sex",None) e=request.POST.get("email",None) # ---------表中插入数据方式一 # info={"username":u,"sex":e,"email":e} # models.UserInfor.objects.create(**info) # ---------表中插入数据方式二 models.userinfo.objects.create( username=u, sex=s, email=e ) userlist=models.userinfo.objects.all() # for i in userlist: # print(i.username,i.sex,i.email) return render(request,"index.html",{"userlist":userlist})
在显示页面上index.html显示数据库中提取的数据:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/userInfo" method="post"> <p>姓名<input type="text" name="username"></p> <p>性别<input type="text" name="sex"></p> <p>邮箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> <h1>数据展现</h1> <table border=1px> <tr> <td>姓名</td> <td>性别</td> <td>年龄</td> </tr> <tr> {% for i in userlist %} <td>{{i.username}}</td> <td>{{ i.sex }}</td> <td>{{ i.email }}</td> </tr> {% endfor %} </table> </body> </html>
#返回数据:HttpResponse("str") return render(request,"html文件路径","html中要替换的变量":USER_LIST) return redirect("/只能填URL路径")
7.模板渲染
模板语言:
--{{变量名}} def func(request): return render(request,'index.html',{'current_user':"alex"}) index.html中 <html> ........ <body> <div>{{current_user}}</div>#这样用alex替换了current_user </body> </html> --For循环 userlist=[] def userInfo(request): if request.method=="POST": username=request.POST.get("username",None) sex=request.POST.get("sex",None) email=request.POST.get("email",None) user={"username":username,"sex":sex,"email":email} userlist.append(user) return render(request,"index.html",{"userlist":userlist}) index.html中 <html> ........ <body> <table border=1px> <tr> <td>姓名</td> <td>性别</td> <td>邮箱</td> </tr> <tr> {% for i in userlist %} <td>{{i.username}}</td> <td>{{ i.sex }}</td> <td>{{ i.email }}</td> </tr> {% endfor %} </table> </body> </html> --索引 def func(request): return render(request,'index.html',{ 'current_user':"alex", 'user_list':['xiaoming','liangliang'] 'user_dict':{'k1':'v1','k2':'v2'}}) index.html中 <html> ........ <body> <a>{user_list.0/1}</a> </body> </html> --条件 {%if age %} <a>有年龄</a> {% else %} <a>无年龄</a> {% endif %} --循环字典 {%for k,row in dict.items%}#同时得到key和value <li>{{k}}-{{row}}</li> {%endfor%} {%for row in dict.keys%}#得到字典中的key <li>{{row}}</li> {%endfor%} {%for row in dict.values%}#得到字典中的value <li>{{row}}</li> {%endfor%}