什麼是web應用?css
Web應用程序是一種能夠經過Web訪問的應用程序,程序的最大好處是用戶很容易訪問應用程序,用戶只須要有瀏覽器便可,不須要再安裝其餘軟件
應用程序有兩種模式C/S、B/S。C/S是客戶端/服務器端程序,也就是說這類程序通常獨立運行。而B/S就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助IE等瀏覽器來運行。WEB應用程序通常是B/S模式。Web應用程序首先是「應用程序」,和用標準的程序語言,如C、C++等編寫出來的程序沒有什麼本質上的不一樣。然而Web應用程序又有本身獨特的地方,就是它是基於Web的,而不是採用傳統方法運行的。換句話說,它是典型的瀏覽器/服務器架構的產物。
Web應用程序的優勢
網絡應用程序不須要任何複雜的「展開」過程,你所須要的只是一個適用的瀏覽器;
網絡應用程序一般耗費不多的用戶硬盤空間,或者一點都不耗費;
它們不須要更新,由於全部新的特性都在服務器上執行,從而自動傳達到用戶端;
網絡應用程序和服務器端的網絡產品都很容易結合,如email功能和搜索功能;
由於它們在網絡瀏覽器窗口中運行,因此大多數狀況下它們是經過跨平臺使用的 (例如Windows,Mac,Linux等等)
Web應用程序的缺點
網絡應用程序強調瀏覽器的適用性。若是瀏覽器方沒有提供特定的功能,或者棄用特定的平臺或操做系統版本(致使不適用),就會影響大量用戶;
網絡應用依靠互聯網遠程服務器端的應用文件。所以,當鏈接出問題時,應用將不能正常使用。
許多網絡應用程序不是開源的,只能依賴第三方提供的服務,所以不能針對用戶定製化、個性化,並且大多數狀況下用戶不能離線使用,於是損失了不少靈活性;
它們徹底依賴應用服務商的可及性。若是公司倒閉,服務器中止使用,用戶也沒法追索之前的資料。對比而看,即便軟件製造商倒閉了,傳統的安裝軟件也能夠繼續運行,儘管不能再更新或有其餘用戶服務;
類似地,提供方公司對軟件和其功能有了更大的控制權。只要他們願意就能爲軟件添加新特性,即便用戶想等bugs先被解決再更新。跳過較差的軟件版本也不可能了。公司能夠強加不受歡迎的特性給用戶,也能夠隨意減小帶寬來削減開支。
公司理論上能夠檢索任何的用戶行爲。這有可能引發隱私安全問題。
B/S架構優勢
瀏覽器/服務器架構(Browser/Server,簡稱B/S)可以很好地應用在廣域網上,成爲愈來愈多的企業的選擇。瀏覽器/服務器架構相對於其餘幾種應用程序體系結構,有以下3方面的優勢:
這種架構採用Internet上標準的通訊協議(一般是TCP/IP協議)做爲客戶機同服務器通訊的協議。這樣可使位於Internet任意位置的人都可以正常訪問服務器。對於服務器來講,經過相應的Web服務和數據庫服務能夠對數據進行處理。對外採用標準的通訊協議,以便共享數據。
在服務器上對數據進行處理,就處理的結果生成網頁,以方便客戶端直接下載。
在客戶機上對數據的處理被進一步簡化,將瀏覽器做爲客戶端的應用程序,以實現對數據的顯示。再也不須要爲客戶端單獨編寫和安裝其餘類型的應用程序。這樣,在客戶端只須要安裝一套內置瀏覽器的操做系統,直接安裝一套瀏覽器,就能夠實現服務器上數據的訪問。而瀏覽器是計算機的標準設備
總結一下,本質上:瀏覽器是一個socket客戶端,服務器是一個socket服務端
基於socket寫一個web應用 html
import socket """ 請求首行 b'GET / HTTP/1.1\r\n 請求頭(一大堆kv鍵值對) Host: 127.0.0.1:8080\r\n Connection: keep-alive\r\n Upgrade-Insecure-Requests: 1\r\n User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n Accept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n \r\n 請求體 ' """ server = socket.socket() # 不傳參數默認就是TCP協議 server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() # 阻塞 等待客戶端連接 data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') print(data) # 手動處理http數據獲取用戶訪問的路徑 current_path = data.decode('utf-8').split('\r\n')[0].split(' ')[1] if current_path == '/index': # 路由匹配上以後返回index # conn.send(b'<h1>index</h1>') with open('index.html','rb') as f: conn.send(f.read()) else: # 當匹配不上的時候統一返回404 conn.send(b'404') conn.close()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1> 你好啊 </h1> </body> </html>
基於wsgiref 寫一個簡單web框架前端
from wsgiref.simple_server import make_server from urls import * def run(env,response): """ :param env: 請求相關的信息 :param response: 響應相關的信息 :return: """ print(env) # 是一個大字典 裏面裝了一堆處理好了的鍵值對數據 response('200 OK',[('username','jason'),('password','123')]) # 固定寫法 後面列表裏面一個個元祖會以響應頭kv鍵值對的形式返回給客戶端 # 獲取用戶訪問的路徑 current_path = env.get('PATH_INFO') # if current_path == '/index': # return [b'index'] # elif current_path == '/login': # return [b'login'] # 定義一個存儲函數名的變量名 func = None # 循環比對路由與試圖函數的映射關係 for url_map in urls: # url_map = ('/index',index) if current_path == url_map[0]: func = url_map[1] # 只要匹配成功 直接結束循環 break if func: res = func(env) else: res = error(env) return [res.encode('utf-8')] if __name__ == '__main__': server = make_server('127.0.0.1',8080,run) server.serve_forever()
from views import * urls = [ ('/index',index), ('/login',login), ('/reg',reg), ('/get_time',get_time), ('/get_user',get_user), ('/get_db', ), ]
import time from jinja2 import Template import pymysql def index(env): return 'index' def login(env): return 'login' def reg(env): return 'reg' def get_time(env): # 先獲取當前時間 current_time = time.strftime('%Y-%m-%d %X') # 打開html文件讀取內容返回給客戶端 with open(r'templates/get_time.html','r',encoding='utf-8') as f: data = f.read() # 由於是以r模式打開的文件,全部獲取到的內容就是一堆字符串 res = data.replace('@@time@@',current_time) # 字符串的替換 return res def get_user(env): with open(r'templates/get_user.html','r',encoding='utf-8') as f: data = f.read() tmp = Template(data) # 將字典傳遞給前端頁面 前端經過變量名user_dic就能夠獲取到該字典 return tmp.render(user_dic={'name':"jason",'password':'123'}) def get_db(env): # 鏈接數據庫 獲取數據 渲染到前端頁面 conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'day54', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute('select * from userinfo') user_dict= cursor.fetchall() # [{},{},{},{}] with open(r'templates/get_db.html','r',encoding='utf-8') as f: data = f.read() tmp = Template(data) return tmp.render(user_dict=user_dict) def error(env): return '404 error'
創一個templates文件專門存放html文件 模板語法python
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <table class="table table-hover table-striped table-bordered"> <thead> <tr> <th>id</th> <th>name</th> <th>password</th> </tr> </thead> <tbody> {% for user in user_dict %} <!--[{},{},{},{}]--> <tr> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.password }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> {{ user_dict }} <!--[{},{},{},{}]--> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> @@time@@ </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <p>{{ user_dic }}</p> <p>{{ user_dic.name }}</p> <p>{{ user_dic['password'] }}</p> <p>{{ user_dic.get('name') }}</p> </body> </html>
c/s架構
客戶端
服務端
b/s架構
瀏覽器
服務器
本質:b/s架構其實也是c/s架構
HTTP協議 超文本傳輸協議:規定了客戶端與服務端消息傳輸的格式 四大特性: 1 基於TCP/TP協議做用於應用層的協議 2 基於請求響應 3 無狀態 4 無鏈接 數據格式之請求: 請求首行 請求頭(一堆k,v鍵值對) 記得要有空格一行 請求體(post請求攜帶的數據) 數據格式之響應: 響應首行 響應頭(一堆k,v鍵值對) 響應體(post請求攜帶的數據) 響應狀態碼 1XX 服務器已經成功接收到你的數據正在處理,你能夠繼續提交其餘數據 2XX 請求成功 服務器已經將你請求的數據發給你了 3XX 重定向 4XX 請求資源不存在 5XX 服務器錯誤
動靜態網頁
靜態網頁:頁面上的數據都是寫死的,萬年不變
動態網頁: 頁面上的數據是從後端動態獲取的
好比後端獲取當前時間
後端獲取數據庫數據而後傳遞給前端頁面
模板渲染
後端生成的數據直接傳遞給前端頁面使用(而且前端頁面能夠靈活的操做該數據) >>> 模板語法
模板渲染 模板語法 須要依賴於第三方模塊 pip install jinja2
模板語法 jinja2 支持前端直接使用相似於python的語法操做數據
<p>{{ user_dict }} </p>
<p>{{ user_dict.name }}</p>
<p>{{ user_dict['password'] }}</p>
<p>{{ user_dict.get('name') }}</p>
{% for user in user_dict%} <!--[{},{},{}]-->
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.password }}</td>
</tr>
{% endfor %}
簡易版本的web請求流程圖mysql
templatesjquery
該文件夾存放的就是全部的頁面文件(.html)web
python 三大主流web框架
Django:大而全,自帶了不少功能模塊,相似於航空母艦(缺點:優勢笨重)
Flask:短小精悍,自帶的功能模塊特別少,大部分都是依賴於第三方模塊(小而輕)
Tornado:異步非阻塞 主要用在處理高io 多路複用的狀況 能夠寫遊戲後端
a:socket
b:路由與視圖函數
c:模板渲染
Django:
a用的別人的 wsgiref
b本身寫的
c本身寫的
Flask:
a用戶的別人的 werkzeug
b本身寫的
c用的別人的 jinja2
Tornado:
a,b,c都是本身寫到的
注意事項:sql
1 計算機名稱不能有中文數據庫
2 一個pycharm窗口就是一個項目,不要多個項目放在一個窗口裏面express
3 項目名不能起中文
啓動django時報錯
Django 啓動時報錯 「UnicodeEncodeError ...」
報這個錯誤一般是由於計算機名爲中文,改爲英文的計算機名重啓下電腦就能夠了。
Django 啓動報錯「SyntaxError: Generator expression must be parenthesized」
報這個錯很大多是由於使用了Python3.7.0,而目前(2018-06-12)Python3.7.0和Django還有點兼容性問題,換回Python3.6的環境便可。
版本問題
Django下載 推薦下載1.11.11版本
下載方式
命令行直接下載
pip3 install django==1.11.11
pycharm下載
驗證是否下載成功
django-admin
建立django項目的方式
方式1(命令行建立):
建立django項目
django-admin startproject 項目名
建立app應用 須要切換到項目目錄下
python3 manage.py startapp app01
啓動django項目
python3 manage.py runserver
中止django項目
ctrl+c
ps:用命令建立django默認不會自動建立templates文件夾須要本身手動建立(注意該文件夾路徑是夠被添加到配置文件中)
新建立的app要手動在配置文件中註冊才能生效 INSTALLED_APPS
![](http://static.javashuo.com/static/loading.gif)
方式2(pycharm建立)
FILE >>> new project 選擇第二個django 須要注意名字不能有中文,選擇本地的解釋器,勾選後臺管理
建立app
pycharm命令行建立
python3 manage.py startapp app01
Tools下面run manage task 功能欄
啓動點小綠箭頭
強調: 1 用django必定要保證只有一個在運行狀態 切記切記!!!
2 必定要記得清理瀏覽器的緩存 settings >>> Network >>> Disable cache(while DevTools is open) 勾選上
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' # 也能夠簡寫 ]
django各個文件的做用
應用名
migrations 數據庫遷移記錄相關數據
admin.py django後臺管理相關
models.py 模型表相關
views.py 視圖函數相關
項目名
settings.py 配置文件
urls.py 路由與視圖函數的映射關係
templates
項目用到的全部的html文件
manage.py
django入口文件
django小白必會三板斧
from django.shortcuts import render,HttpResponse,redirect HttpResponse 返回字符串 render 返回一個html頁面 def reg(request):
user_dict = {'name':'jason','password':'123'}
return render(request,'reg.html',{'user_dict':user_dict})
def reg(request):
user_dict = {'name':'jason','password':'123'}
return render(request,'reg.html',locals())
redirect 重定向
默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
擴展閱讀:
臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。
A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。
A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。
django 識別到你的代碼變化以後會自動,可是有時候反應輸入比較慢
你能夠手動重啓,你也能夠多刷新幾回瀏覽器
啓動箭頭不當心刪除添加回來