Django框架簡介

 web框架本質

咱們能夠這樣理解:全部的Web應用本質上就是一個socket服務端,而用戶的瀏覽器就是一個socket客戶端。 這樣咱們就能夠本身實現Web框架了。html

import socket server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) print(data)  # 將瀏覽器發來的消息打印出來
    conn.send(b"OK") conn.close()

能夠說Web服務本質上都是在這十幾行代碼基礎上擴展出來的。python

用戶的瀏覽器一輸入網址,會給服務端發送數據,那瀏覽器會發送什麼數據?怎麼發?這個誰來定? 你這個網站是這個規定,他那個網站按照他那個規定,這互聯網還能玩麼?mysql

因此,必須有一個統一的規則,讓你們發送消息、接收消息的時候有個格式依據,不能隨便寫。web

這個規則就是HTTP協議,之後瀏覽器發送請求信息也好,服務器回覆響應信息也罷,都要按照這個規則來。sql

HTTP協議主要規定了客戶端和服務器之間的通訊格式,那HTTP協議是怎麼規定消息格式的呢?數據庫

讓咱們首先打印下咱們在服務端接收到的消息是什麼。express

輸出結果:django

""" 請求首行 b'GET / HTTP/1.1\r\n 請求頭 Host: 127.0.0.1:8080\r\n Connection: keep-alive\r\n Cache-Control: max-age=0\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/75.0.3770.80 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\r\n \r\n 請求體 ...... """

要想讓咱們本身寫的web server端正經起來,必需要讓咱們的Web server在給客戶端回覆消息的時候按照HTTP協議的規則加上響應狀態行,這樣咱們就實現了一個正經的Web框架了flask

import socket server = socket.socket() 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') conn.send(b'hello world') print(data)

咱們經過十幾行代碼簡單地演示了web 框架的本質。後端

接下來就讓咱們繼續完善咱們的自定義web框架吧!

根據不一樣的路徑返回不一樣的內容

這樣就結束了嗎? 如何讓咱們的Web服務根據用戶請求的URL不一樣而返回不一樣的內容呢?

咱們能夠從請求相關數據裏面拿到請求URL的路徑,而後拿路徑作一個判斷...

import socket server = socket.socket() 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') data = data.decode('utf-8')  # 把從瀏覽器那裏收到的字節類型的數據轉換成字符串
    # print(data)
    target_url = data.split('\r\n')[0].split(' ')[1]  #按\r\n分割
    # 根據不一樣的路徑返回不一樣內容
    if target_url == '/index': # conn.send(b'index')
        with open(r'D:\demo.html','rb') as f: conn.send(f.read()) elif target_url == '/login': conn.send(b'login') else: conn.send(b'404 error') conn.close()

基於wsgiref模塊:

根據功能的不一樣拆分紅不一樣的文件,用戶在瀏覽器窗口輸入url之因此可以獲取到相應的資源,是由於後端早已經開設了相應的資源接口 

基於wsgiref模塊以及文件拆分的特色:

若要開設新的資源
1.先在urls文件中寫url與函數的對應關係
2.再去views文件中寫對應的函數

urls.py:路由與視圖函數的對應關係
views.py:裏面就是放的一堆視圖函數(視圖函數能夠是函數也能夠是類)
templates文件夾:裏面放的就是一堆html文件(模板文件夾)

動靜態網頁

靜態網頁:數據是寫死的,萬年不變

動態網頁:數據是動態獲取的,如獲取當前時間,從數據庫中取數據

jinja2模塊 

提供了一個能夠在html頁面上書寫相似於python後端的代碼 來操做數據(模板語法) ,flask框架模板語法使用的就是jinja2模塊,因此你只要下了flask框架 就會自動下載jinja2 

模板語法(jinja2模板語法很是貼近python語法 可是並非全部的框架使用的都是jinja模板語法)

{{ 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>
View Code
{%for user_dict in xxx %} <tr>
        <td>{{ user_dict.id }}</td>
        <td>{{ user_dict.name }}</td>
        <td>{{ user_dict.hobby }}</td>
    </tr> {% endfor %}
View Code

基於wsgiref模塊、jinjia2實現web框架

from views import * urls = [ ('/index',index), ('/login',login), ('/xxx',xxx), ('/get_time',get_time), ('/get_user',get_user), ('/get_info',get_info) ]
urls.py
def index(env): return 'index'

def login(env): return 'login'

def error(env): return '404 error'

def xxx(env): return 'xxx'

import time def get_time(env): # 該函數須要返回一個html頁面
    current_time = time.strftime('%Y-%m-%d %X') # 文件操做 讀取html文件
    with open(r'F:\python\templates\02 get_time.html','r',encoding='utf-8') as f: data = f.read()  # html文件內容 字符串
    data = data.replace('gfdgsffsda',current_time)  # 利用字符串的替換
    return data from jinja2 import Template def get_user(env): user_dict = {'username':'jason','password':123,'hobby':['read','study','run']} with open(r'F:\python\templates\04 get_info.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(xxx=user_dict)  # 將user_dict傳遞給html頁面 在頁面上經過變量名xxx就可以獲取到user_dict
    return res import pymysql def get_info(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'day49', charset = 'utf8', autocommit = True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from userinfo" cursor.execute(sql) data = cursor.fetchall()  # [{},{},{}]
    # 將列表套字典的結構數據 直接傳遞給html頁面
    with open(r'D:get_info.html','r',encoding='utf-8') as f: res = f.read() # 利用jinja2模塊
    tmp = Template(res) # 利用對象的render方法 將數據直接傳遞給html頁面
    res = tmp.render(xxx=data) return res
views.py
from wsgiref.simple_server import make_server from views import *
from urls import urls def run(env,response): """ :param env: 請求相關的全部數據 :param response: 響應相關的全部數據 :return: 瀏覽器可以接受的內容 """ response('200 OK',[]) # print(env) # env是一個大字典 裏面的PATH_INFO參數就是用戶輸入的後綴
    target_url = env.get('PATH_INFO') # if target_url == '/index':
    # # 一堆邏輯判斷
    # return [b'index']
    # elif target_url == '/login':
    # return [b'login']
    # 先定義一個變量 用來存儲可能匹配到的函數名
    func = None # 1 for循環獲取一個個的url與函數對應關係的元組
    for url in urls:  # url = (),(),()
        # 2 判斷當前用戶訪問的url與元組第一個元素是否一致
        if target_url == url[0]: # 3 若是相等 說明有對應的後端邏輯代碼 將匹配到的函數名賦值給func
            func = url[1] # 4 一旦用戶匹配上了響應的url 應該馬上結束當前for循環了 由於再循環就沒有意義
            break
    # 針對func是否有值 還須要判斷
    if func: # 匹配上了 加括號直接調用
        res = func(env) else: # 匹配404邏輯代碼
        res = error(env) return [res.encode('utf-8')]  # 返回函數的返回值


if __name__ == '__main__': # 監聽127.0.0.1:8080 一旦有客戶端來訪問 會馬上將make_server第三個參數加括號調用執行
    server = make_server('127.0.0.1',8080,run) server.serve_forever() # 啓動服務端
wsgiref

web框架簡介

python三大主流web框架

Django  優點:大而全,自身攜帶的組件和功能特別多,就相似於航空母艦。不足之處:笨重

Flask  優點:小而精,自身攜帶的組件和功能特別少,就相似於遊騎兵,雖然自身功能比較少,可是第三方支持該框架的模塊不少若是你將flask第三方模塊所有疊加起來甚至能夠超過django  不足之處:受限於第三方模塊 

Tornado  異步非阻塞,自然支持高併發 甚至能夠用它來開發遊戲服務器

Django框架

Django框架注意事項:

  1. 計算機名稱不能有中文 
  2. 項目文件名也不要用中文 
  3. 一個pycharm窗口就是一個單獨的完整的項目 

Django版本:

推薦使用1.X版本里面的1.11.09~1.11.13

安裝

pip3 install django==1.11.11

#測試是否安裝成功
命令行輸入 django-admin

建立django項目的兩種方式

1.使用命令行建立

建立django項目:
django-admin startproject mysite(項目名)

效果:建立了一個mysite的文件夾

目錄介紹
mysite/ ├── manage.py # 管理文件
└── mysite  # 項目目錄
    ├── __init__.py ├── settings.py # 配置
    ├── urls.py  # 路由 --> URL和函數的對應關係
    └── wsgi.py  # runserver命令就使用wsgiref模塊作簡單的web server
啓動Django項目:
python manage.py runserver  # django默認的端口號是8000

Django 若啓動報錯「SyntaxError: Generator expression must be parenthesized」

報這個錯很大多是由於使用了Python3.7.0,而目前(2018-06-12)Python3.7.0和Django還有點兼容性問題。解決方案以下

Django 啓動時報錯 「UnicodeEncodeError ...」

報這個錯誤一般是由於計算機名爲中文,改爲英文的計算機名重啓下電腦就能夠了。

建立具備獨立功能的app
python manage.py startapp app01  #一般狀況下應該作到見名知意 

  app01
    -- migrations 文件夾
    -- __init__.py
    -- admin.py
    -- apps.py
    -- models.py
    -- tests.py
    -- views.py

app(application)的概念

django實際上是一個專一於開發app的web框架,一個空的django項目就相似因而一所大學,app就相似於大學裏面的各個學院。

每一個app其實就相似於不一樣的功能模塊

  購物網站
    用戶相關 user
      用戶相關的app
    訂單相關 order
      訂單相關的app
    投訴相關 tousu
      投訴相關的app

不一樣的功能模塊推薦使用不一樣的app去開發,django支持多app

Django主要文件功能
 mysite -mysite --__init__.py --settings.py 項目配置文件 --urls.py 路由視圖函數對應關係 項目的總路由 --wsgi.py -manage.py
app01
--migrations文件夾 數據庫改動記錄 --__init__.py --__init__.py --admin.py django後臺管理 --apps.py 註冊app相關 --models.py 模型類(ORM) --tests.py 測試文件 --views.py 視圖函數(******)


     db.sqlite3 django自帶的一個小型用於本地測試的數據庫(對日期格式的數據不是很敏感)

2.使用pycharm建立

注意:1.使用命令行建立的django項目是不會自動建立templates模板文件夾,只能本身手動建立

2.命令行建立的django項目不但沒有templates文件夾,配置文件中也沒有填寫路徑,而pycharm建立的會自動添加


 容易犯的錯誤:代碼修改了始終沒有效果

1.在同一個端口起了多個服務 一直跑的是最開始的那個服務
2.瀏覽器緩存問題


解決瀏覽器緩存以下圖

 

 補充:簡化命令的方式

項目配置文件夾註意事項:(註冊)

注意:建立app以後必定必定要先去setting文件中註冊

 

pycharm建立的Django項目的配置文件

命令行建立的Django項目的配置文件

 

Django可以自動重啓,可是它的重啓機制只要檢測到你的代碼有變化,則在必定的時間間隔內就會自動重啓。因此有時候可能會出現 你代碼還沒寫完就已經自動重啓了

Django基礎必備三件套

HttpResponse:返回字符串

render:返回html頁面 並能夠給html頁面傳數據

    模板的渲染(將數據在後端按照模板語法放入html對應的位置)

redirect:重定向

from django.shortcuts import render,HttpResponse,redirect # Create your views here.
def index(request): return HttpResponse('字符串') def login(request): return render(request,'templates文件夾下的html文件名',{'user_dict':{'username':'jason','password':123},'userxxx':'hello world'})) def home(request): # return redirect('http://www.baidu.com')
    return redirect('/index')
相關文章
相關標籤/搜索