全部的Web應用本質就是一個socket服務端,用戶使用的瀏覽器就是socket客戶端html
軟件開發架構:C/S架構和B/S架構,B/S架構本質也是C/S前端
一、純手擼簡易版web框架,實現根據用戶輸入的後綴不一樣內容返回不一樣的結果python
import socket server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) # Http協議的響應信息,HTTP/1.1表示當前協議爲Http。1.1是協議的版本。200表示成功, OK表示好的 conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # print(data) data = data.decode('utf8') # 返回的是一串字符串,第二個字符串就是用戶輸入的後綴 # 獲取用戶輸入的後綴內容 target_url = data.split('\r\n')[0].split(' ')[1] # 判斷用戶輸入的內容返回不一樣的內容 if target_url == 'index': conn.send(b'index') elif target_url == 'login': conn.send(b'login') else: conn.send(b'404 error') conn.close()
因爲socket代碼是咱們本身寫的,HTTP數據也是咱們本身處理的太過麻煩,因此有了wsgiref模塊mysql
二、wsgiref模塊web
wsgiref模塊能夠幫咱們封裝咱們寫的web框架中的socket server部分sql
把路由關係與函數對應關係全寫在一個py文件太過冗餘,因此根據功能不一樣拆分紅不一樣的文件:數據庫
urls.py:路由與視圖函數的對應關係django
views.py:裏面就是存放一堆視圖函數(視圖函數能夠是函數也能夠是類)flask
templates文件夾(模板文件夾):裏面放一堆HTML文件後端
用戶在瀏覽器窗口輸入url之因此能獲取相應的資源是由於後端早已經開設相應的資源接口
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env, response): ''' :param env: 請求相關的全部數據,接收的是大字典,裏面的PATH_INFO參數就是用戶輸入的url後綴 :param response: 響應相關的全部數據 :return: 返回瀏覽器接收的內容 ''' response('200 OK', []) target_url = env.get('PATH_INFO') # 此處應該根據用戶輸入進行邏輯判斷,爲減小代碼用for循環實現 # 先定義一個變量存儲可能匹配的函數名 func = None for url in urls: # 判斷用戶輸入的是否與urls一致 if target_url == url[0]: func = url[1] # 一旦有響應就馬上結束,調轉到響應url break # 判斷是否有匹配上的 if func: # 加括號調用 res = func(env) else: res = error(env) return [res.encode('utf-8')] if __name__ == '__main__': # 監聽'127.0.0.1:9876'一旦有訪問就調用run執行 server = make_server('127.0.0.1', 9876, run) # 啓動服務端 server.serve_forever()
基於wsgiref模塊已經文件拆分的特色,在後端開設相應的資源接口1. 先在urls文件中寫url與函數對應的關係。2. 再去views文件中寫對應的函數
from views import * urls = [ ('/index', index), ('/login', login), ('/get_time', get_time), ]
def index(env): return 'index' def login(env): return 'login' def error(env): return '404 error'
# 須要返回一個HTML頁面能實時獲取時間的 import time def get_time(env): current_time = time.strftime('%Y-%m-%d %X') with open(r'E:\Python\templates\get_time.html','r',encoding='utf-8') as f: data = f.read() # 將HTML中的文本xxx替換成當前時間 data = data.replace('xxx',current_time) return data
動靜態網頁:靜態網頁:數據是寫死的,不變的
動態網頁:數據是動態獲取的,好比獲取當前時間,從數據庫中獲取數據
三、jinja2模塊
提供了一個能夠在HTML頁面上書寫相似於python後端的代碼,來操做數據(模板語法)
下載:pip3 install jinja2
flask框架模板語法使用的就是jinja2模塊,全部下載了flask框架就自動下載了jinja2模塊
jinja2模板語法很是貼近python語法,可是並非全部的框架使用的都是jinja2模板語法
模板語法:在HTML中使用相似於python語法,本質在後端實現的,前端根本不識別
from jinja2 import Template def get_info(env): user_dic = {'username': 'shen', 'password': 123, 'hobby': ['study','read']} with open(r'E:\Python\templates\get_info.html','r', encoding='utf8') as f: data = f.read() temp = Template(data) res = temp.render(xxx=user_dic) return res
/-{{}}雙大括號表示變量相關-/
{{xxx}} <p>{{xxx.username}}</p> <p>{{xxx['password']}}</p> <p>{{xxx.get('hobby')}}</p> <p>{{xxx.get('hobby')[0]}}</p> <p>{{xxx.get('hobby').1}}</p>
/-{% %} 大括號內有%%表示邏輯相關-/ {%for user_dict in xxx %} <tr> <td>{{ user_dict.password }}</td> <td>{{ user_dict.username }}</td> <td>{{ user_dict.hobby }}</td> </tr> {% endfor %}
四、獲取數據庫中的數據展現到前端頁面
一、路由與視圖函數對應關係
二、視圖函數
三、模板文件夾
四、模板語法(是在後端實現的,前端根本不識別)
import pymysql
def get_user(env):
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
database='dome',
charset='utf8',
user='root',
password='2694',
autocommit=True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = 'select * from user_info'
cursor.execute(sql)
data = cursor.fetchall()
with open(r'E:\Python\templates\get_user.html','r',encoding='utf-8') as f:
res = f.read()
tmp = Template(res)
res = tmp.render(xxx=data)
return res
<body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <table class="table table-hover table-bordered"> <thead> <tr> <th>id</th> <th>username</th> <th>password</th> <th>hobby</th> </tr> </thead> <tbody> {%for user_dic in xxx %} <tr> <td>{{ user_dic.id }}</td> <td>{{ user_dic.username }}</td> <td>{{ user_dic.password }}</td> <td>{{ user_dic.hobby }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body>
優勢:大而全,自身攜帶的組件和功能特別多
缺點:笨重,當功能很少時不須要使用不少其餘的功能
socket部分用wsgiref,路由分發用本身寫的,模板渲染本身寫的
優勢:小而精,自身攜帶的組件和功能特別少,可是第三方支持該框架的模塊特別特別多,疊加起來甚至能夠超過Django
缺點:受限於第三方模塊
socket部分用werkzeug,路由分發本身寫的,模板渲染用jinja2
異步非阻塞,自然支持高併發,甚至能夠開發遊戲服務器
socket,路由分發,模板渲染都本身寫
計算機名稱不能有中文
項目文件名也不能有中文
一個pycharm窗口就是單獨的完整的項目
1.xx版本與2.xx版本
推薦使用1.11.09~1.11.13
若是已經安裝不須要手動卸載,從新安裝會自動先卸載以前的版本再安裝
pip3 install django==1.11.11
命令行輸入django-admin
注意:python3.7與1.11.11不兼容能夠更改Django的配置文件中一個數據便可
一、命令行
一、建立Django項目 : django-admin startproject 項目名
例:建立一個mysite項目:django-admin startproject mysite
效果:會建立一個mysite的文件夾
二、啓動Django項目(先切換到項目目錄下)
python manage.py runserver host:port # host:port 能夠不寫 默認是本機的127.0.0.1:8000
三、建立具備獨立功能的app , 一般app名要見名知意:python manage.py startapp app名
例:python manage.py startapp app01
app的概念:application應用
Django實際上是一個專一於開發的app的web框架,一個空的Django框架就相似一所大學,一個個的app就至關於一個個學院,每一個app就相似於不一樣的功能模塊,不一樣的功能模塊推薦使用不一樣的app去開發,Django支持多app
注意:一、使用命令行建立的Django項目不會建立templates模板文件夾,只能手動建立
二、命令行建立的Django項目配置文件settings中沒有填寫路徑須要手動添加到環境變量中,pycharm建立的就會自動添加
二、pycharm快捷建立
pycharm啓動Django
pycharm快捷建立app,會自動在配置文件中註冊
mysite/ ├── manage.py # 管理文件 ├── db.sqlite3 # django自帶的一個小型用於本地測試的數據庫(對日期格式的數據不是很敏感) └── mysite # 項目目錄 ├── __init__.py ├── settings.py # 配置 ├── urls.py # 路由 --> URL和函數的對應關係 └── wsgi.py # runserver命令就使用wsgiref模塊作簡單的web server └── app01 # 建立的app ├──migrations文件夾 數據庫改動記錄 ——__init__.py ├── __init__.py ├── admin.py # Django後臺管理 ├── apps.py # 註冊app相關 ├── models.py # 模型類(ORM) ├── tests.py # 測試文件 └── views.py # 視圖函數
(*********)注意建立app後必定要先去settings文件中註冊
修改代碼始終沒有效果
一、在同一個端口起了多個服務一直運行的是最開始的那個服務
二、瀏覽器緩存問題
一、HttpResponse:返回字符串
def index(request):
# return HttpResponse('字符串') return HttpResponse('你好 美女')
二、render:模板渲染(將數據在後端按照模板語法放入HTML對應的位置)
返回html頁面,而且能夠給HTML頁面傳數據
def login(request):
# return render(request, 'templates文件夾下的html文件',{傳給HTML頁面的數據}) return render(request,'login.html',{'user_dict':{'username':'shen','password':123},'xxx':'hello world'})
三、redirect:重定向
能夠重定向到本身寫的url上能夠簡寫url只寫結尾
也能夠重定向到指定的url
def home(request): # return redirect('https://www.mzitu.com') return redirect('/index')
Django頁面能夠改爲中文的,在配置文件中更改爲下面的就行
LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False