框架,即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%}