##web請求流程css
#一、軟件開發架構
c/s架構
客戶端
服務端
b/s架構
瀏覽器
服務器
本質:b/s架構其實也是c/s架構
#二、問題:當咱們在瀏覽器中輸入一個url地址的時候, 按下回車的那一剎那, 好比ww.baidu.com 描述一下具體的過程. 首先咱們經過DNS域名解析服務器對該域名進行解析,解析順序先找本地dns服務器,好比window系統中host文件,找不到就找根域名解析服務器,全球總共十三臺,而後依次找頂級域名服務器.com、權威域名服務器baidu.com、而後二級域名服務器www,當找到www.baidu.com對應的IP地址之後,便向該服務器發送請求,服務器反饋一個響應結果 #三、Http協議介紹
超文本傳輸協議:規定了客戶端與服務端消息傳輸的格式
#3-一、四大特性:
1.基於TCP/IP協議做用於應用層的協議
2.基於請求響應
3.無狀態
4.無鏈接
#3-二、數據格式之請求:
請求首行
請求頭(一堆k,v鍵值對)
請求體(post請求攜帶的數據)
請求頭: GET / HTTP/1.1 Host: 127.0.0.1:8080 (主機名) Connection: keep-alive (保持連接) Cache-Control: max-age=0 (緩存不失效) Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Token: bdsjalbdjsalbdjsa 請求體(兩個換行符\r\n\r\n後面的內容): bdsabdjsabjddas
#3-三、數據格式之響應:
響應首行
響應頭(一堆k,v鍵值對)
響應體(post請求攜帶的數據)
響應頭: HTTP/1.1 200 OK 響應體: 本身看到的內容 ps: http: 默認端口是80 Https: 默認的端口是443 狀態碼:(*****************************)
1XX:服務器已經成功接受到你的數據正在處理,你能夠繼續提交其餘數據 2XX: 200 (ok)請求成功 服務器已經將你請求的數據發送給你了 3XX: 302 304重定向 4XX: 404(not found) 403(forbidden 禁止訪問)請求資源不存在 5XX: 500 (服務端代碼錯誤) 502 (網關錯誤 bad gateway) #四、字符串和字節的轉換: >>> s = "hello" >>> s 'hello' >>> bytes(s,encoding='utf-8') b'hello' >>> b = bytes(s,encoding='utf-8') >>> str(b, encoding='utf-8')
##自定義web框架html
#一、需求:想要經過輸入不一樣的 url, 得到不同的相應內容 #解決思路: #step 一、建立sokect 服務端: 該socket服務器接收瀏覽器客戶端發來的請求頭中獲取uri路徑,運用了split方法取值 #step 二、路由系統: uri 和 函數的 對應關係 :(注意自定義的緣由,這裏讀每個html文件都須要本身打開進行讀,而後函數return進行返回) routes = [ ('/xxx', f1), ('/ooo', f2), ('/hhh', f3) ] #step 三、模板引擎渲染,顯示給用戶 將html代碼和mysql的數據進行手動融合,而後再替換html中自定義的內容,好比案例中自定義內容@@content@@
(本身定製規則須要本身拼接格式 , 或者使用第三方的工具,好比jinjia2模塊)
後端生成的數據直接傳遞給前端頁面使用(而且前端頁面能夠靈活的操做改數據) >>> 模板語法
模板渲染 模板語法須要依賴於第三方模塊
pip install jinja2
templates:改文件夾存放就是全部的頁面文件(.html)
模板語法 jinja2支持前端直接使用相似於python的語法操做數據
<p>{{ user_dic }}</p>
<p>{{ user_dic.name }}</p>
<p>{{ user_dic['password'] }}</p>
<p>{{ user_dic.get('name') }}</p>
{% for user in user_dict %} <!--[{},{},{},{}]-->
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.password }}</td>
</tr>
{% endfor %} #案例 *****自定製server.py***** import socket import time def f1(): fp = open('index.html','r',encoding='utf-8') data = fp.read() fp.close() return bytes(data,encoding='utf-8') def f2(): fp = open('article.html','r',encoding='utf-8') data = fp.read() ctime = time.time() data = data.replace('@@content@@',str(ctime)) return bytes(data, encoding='utf-8') def f3(): import pymysql conn = pymysql.connect(host='127.0.0.1',user='root',password='123',db='db1',charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select id,name,depart_id from userinfo' cursor.execute(sql) res = cursor.fetchall() print(res) res_list = [] for user in res: res_str = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>"%(user["id"],user['name'],user["depart_id"]) res_list.append(res_str) s="".join(res_list) fp = open('content.html','r',encoding='utf-8') data = fp.read() fp.close() data = data.replace("@@content@@", s) return bytes(data,encoding='utf-8') def f4(): import pymysql conn = pymysql.connect(host='127.0.0.1',user='root',password='123',db='db1',charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select id,name,depart_id from userinfo' cursor.execute(sql) users = cursor.fetchall() # print(res) fp = open('content-jinjia2.html','r',encoding='utf-8') data = fp.read() fp.close() from jinja2 import Template template = Template(data) data = template.render(users = users) return bytes(data,encoding='utf-8') routers = ( ('/ooo',f1), ('/xxx',f2), ('/hhh',f3), ('/kkk',f4) ) def run(): server = socket.socket() server.bind(("127.0.0.1",1688)) server.listen(5) while True: client,addr = server.accept() buf = client.recv(1024) data = str(buf,encoding='utf-8') header_list = data.split('\r\n\r\n')[0].split('\r\n')[0] uri = header_list.split(' ')[1] #第一種方式:缺點:擴展性差 # res = None # if uri == '/xxx': # res = bytes("this is xxx",encoding='utf-8') # elif uri == '/ooo': # res = bytes("this is ooo", encoding='utf-8') # else: # res = bytes('404 not fund',encoding='utf-8') #第二種:路由方式 func_name = None for item in routers: if uri == item[0]: func_name = item[1] break if func_name: res = func_name() else: res = b'404 not fund' client.send(bytes('HTTP/1.1 200 OK\r\n\r\n',encoding='utf-8')) client.send(res) client.close() if __name__ == '__main__': run() *************index.html 靜態顯示********** <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>this is index</h1> </body> </html> ***********article.html 能夠替換自定義內容動態顯示時間********** <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> @@content@@ </body> </html> *********content.html 能夠替換自定義顯示內容********* <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>ID</th> <th>Name</th> <th>department_id</th> </tr> </thead> <tbody> @@content@@ </tbody> </table> </body> </html> *********content-jinjia2.html使用第三方工具渲染********* <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>ID</th> <th>Name</th> <th>department_id</th> </tr> </thead> <tbody> {%for item in users%} <tr> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.depart_id}}</td> </tr> {%endfor%} </tbody> </table> </body> </html>
#二、web框架分類:
a. sokect 服務端 b、路由系統 c、模板引擎渲染
第一種維度分類:
- a,b,c ----> tornado
- a(用第三方), b, c ----> django wsgiref uwsgi
- a(第三方),b, c(第三方) -----》 flask
注:
python三大主流web框架
Django:大而全,自帶了不少功能模塊,相似於航空母艦 (缺點:有點笨重)
Flask:短小精悍,自帶的功能模塊特別少,大部分都是依賴於第三方模塊(小而輕)
Tornado:異步非阻塞 主要用在處理高io 多路複用的狀況 能夠寫遊戲後端
第二種維度:
- django
- 其餘
##Django基礎前端
#一、安裝: pip3 install django==1.11.10 -i https://pypi.tuna.tsinghua.edu.cn/simple #二、建立: 建立django項目的方式
方式1(命令行建立):
建立django項目
django-admin startproject 項目名
建立app應用
python3 manage.py startapp app01
啓動django項目
python3 manage.py runserver
ps:用命令行建立django默認不會自動建立templates文件夾
須要你手動本身建立(注意改文件夾路徑是否被添加配置文件中)
方式2(pycharm建立)
FILE >>> new project 選擇第二個django 須要注意名字不能有中文,選擇本地的解釋器,勾選後臺管理
建立app
pycharm命令行建立
python3 manage.py startapp app01
Tools下面run manage task功能欄
啓動點小綠色箭頭
強調:
1.用django必定要保證只有一個在運行狀態 切記切記!!!!!!!
2.必定記得清瀏覽器的緩存
app(應用)的概念
一個django項目就是一所大學
app就是大學裏面的學院
注意新建立的app須要在配置文件中註冊才能生效(*******************)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config' # 能夠用全稱
'app01' # 也能夠簡寫
] #三、目錄介紹: 應用名
migrations 數據庫遷移記錄相關數據
admin.py django後臺管理相關
models.py 模型表相關
views.py 視圖函數相關 mysite: mysite項目名: settings.py : 用戶自定義的各類配置 urls.py : 路由與視圖含書映射關係 wsgi.py : 啓動socket服務端的 文件 mange.py: django入口文件、 管理文件、 python mange.py 各類命令
templates:項目用到的全部的html文件 js, css, img : 靜態 文件 #四、之後建立django完成以後: a. 配置末班文件路徑: 'DIRS': [os.path.join(BASE_DIR, 'templates')] b. 配置靜態資源的文件路徑: STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), (逗號不能少) ) c. 註釋中間件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
#五、寫業務邏輯的話:
uri和函數的對應關係:
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^index/', index),
]
業務邏輯函數:
def index(request):
return render(request, "index.html")
##Django + 前端表單提交數據到後臺python
#django小白必會三板斧
# HttpResponse:它是做用是內部傳入一個字符串參數,而後發給瀏覽器。 # render:render方法可接收三個參數,一是request參數,二是待渲染的html模板文件,三是保存具體數據的字典參數。 它的做用就是將數據填充進模板文件,最後把結果返回給瀏覽器。與jinja2相似。 #redirect 重定向 又走了一次網絡請求 注意:django必會三板斧返回的都是HttpReponse對象
#一、建立一個Django項目(功能:數據庫驗證登陸、登錄失敗標紅重新渲染、登錄成功跳轉) #1-一、完成三件事(上述有講解 ,此處省略) #1-二、路由文件urls.py中 添加路由 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',index), url(r'^login/',login), ] 建立相對應函數 def index(request): return render( request, 'index.html', { "username":"icon", "mylist":["icon",'is','18'], "mydict":{"name":"icon","age":"18"}, "userinfo":[ {"name":"icon1","age":"18","sex":"male"}, {"name":"icon2","age":"19","sex":"male"}, {"name":"icon3","age":"20","sex":"male"}, {"name":"icon4","age":"21","sex":"male"}, ] }, ) def login(request): if request.method == 'GET': return render(request,'login.html') else: import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password='123', db='db1', charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from user' cursor.execute(sql) # 數據庫數據列表套字典 users = cursor.fetchall() #前端傳過來的用戶信息和密碼 username = request.POST.get('username') password = request.POST.get('password') for user in users: if username == user.get('username') and password == user.get('password'): return HttpResponseRedirect("/index/") return render(request,'login.html',{'error_msg':'用戶名或密碼錯誤'}) #1-三、在templates目錄建立index.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#一、渲染:變量替換,替換的key必須和urls.py文件中一一對應#} {{ username }} <hr> {#二、渲染:列表替換#} {#{{ mylist.0 }}#} {#{{ mylist.1 }}#} {#{{ mylist.2 }}#} <ul> <li>{{ mylist.0 }}</li> <li>{{ mylist.1 }}</li> <li>{{ mylist.2 }}</li> </ul> <hr> {#三、渲染:列表循環替換#} <ul> {% for item in mylist %} <li> {{ item }} </li> {% endfor %} </ul> <hr> {#四、渲染:字典循環替換顯示給用戶#} {% for key,val in mydict.items %} <li> {{ key }} --- {{ val }} </li> {% endfor %} <hr> {% for key in mydict.keys %} <li> {{ key }} </li> {% endfor %} <hr> {#五、渲染:表格#} <table border="1px"> <thead> <tr> <th>name</th> <th>age</th> <th>sex</th> </tr> </thead> <tbody> {% for user in userinfo %} <tr> <td>{{ user.name }}</td> <td>{{ user.age }}</td> <td>{{ user.sex }}</td> </tr> {% endfor %} </tbody> </table> </body> </html> #1-四、在templates目錄建立login.html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {# <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.css">#} </head> <body> <form action="/index/" method="post"> 用戶名:<input type="text" name="username" ><br> 密碼:<input type="password" name="password"> <i style="color: red;">{{ error_msg }}</i><br> <input type="submit" value="登陸"> </form> </body> {#<script src="../js/jquery-3.4.1.js"></script>#} {#<script src="../bootstrap-3.3.7-dist/js/bootstrap.js"></script>#} </html>