Django 14天從小白到進階- Day1 Django 初識


 

本節內容

 

Http原理介紹

自行開發一個Web框架

WSGI介紹

Django介紹

MVC/MTV

Django安裝

創建項目與APP

開發第一個頁面

 

為什么學Django?

Good question , 知Python者必知Django, 因為這可是Python語言里最流行&強大的Web框架,同時亦是全球第5大WEB框架,可快速構建穩定強大的WEB項目,大大提高開發效率,很多知名項目都是基於Django開發,如Disqus、Pinterest、Instagram、Bitbucket等, Django官方Slogan是The framework for perfectionist with deadline! 一個為完美主義者且又開發工期很緊的人設計的框架,事實確實如此,Django自身集成了豐富的WEB開發通用組件,如用戶認證、分頁、中間件、緩存、session等,可以避免浪費大量時間重復造輪子。

 

Http原理介紹

HTTP協議(HyperText Transfer Protocol,超文本傳輸協議)是用於從WWW服務器傳輸超文本到本地瀏覽器的傳送協議。它可以使瀏覽器更加高效,使網絡傳輸減少。它不僅保證計算機正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內容首先顯示(如文本先於圖形)等。

HTTP協議通常承載於TCP協議之上,有時也承載於TLS或SSL協議層之上,這個時候,就成了我們常說的HTTPS。如下圖所示:

HTTP協議永遠都是客戶端發起請求,服務器回送響應。見下圖:

 

這個Client和Server端本質上是一個Socket客戶端和服務器端,Http協議可以說是基於Socket的再上層封裝。

 

 

HTTP特性

基於TCP/IP協議

你每次打開百度或其它網站,都需要先建立好TCP/IP會話,當然這個瀏覽器會幫你做了。

短連接

你打開 https://www.luffycity.com/  或其它網站, 當服務器端把這個頁面的內容全返回后,就把這次連接斷開了,會話就結束了,你在瀏覽器上看到頁面內容已經是下載到本地的了,所以此時如果服務器端更新了內容,你本地的頁面自然是不會跟着變的。除非你再刷新一下,這樣就又進行了一次會話。那為何是短連接呢?你想一想

被動響應

這個很好理解,你不請求百度,百度是不會主動連接你的。

無狀態

無狀態是指,當瀏覽器發送請求給服務器的時候,服務器響應,但是同一個瀏覽器再發送請求給服務器的時候,他會響應,但是他不知道你就是剛才那個瀏覽器,簡單地說,就是服務器不會去記得你,所以是無狀態協議。

 

自行開發一個Web Server

既然Http協議本質上是基於Socket做的,我們又學過Socket了,那能不能自己開發一個Web Server呢? 回答是of course. 

 

# -*- coding:utf-8 -*-
# created by Alex Li - 路飛學城

import socket


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('localhost', 8000))
    sock.listen(5)

    while True:
        # 等待瀏覽器訪問
        conn, addr = sock.accept()
        # 接收瀏覽器發送來的請求內容
        data = conn.recv(1024)
        print(data)

        # 給瀏覽器返回內容
        conn.send(b"HTTP/1.1 200 OK\r\nContent-Type:text/html; charset=utf-8\r\n\r\n")
        conn.send("電腦前的你長的真好看!".encode("utf-8"))

        # 關閉和瀏覽器創建的socket連接
        conn.close()


if __name__ == "__main__":
    main()

  

我靠,這么簡單,是的,就這么簡單,但你現在只是返回了一句話,如果是要返回一個圖片呢?一個文件呢?這就涉及你自己要負責實現文件的傳送了,我們學socket傳文件時,遇到過粘包問題,解決起來挺麻煩的,你現在要自己通過Socket把Http協議里的各種功能都實現了的話,估計孩子都長大了。與其浪費時間自己寫,不如直接用先人的。

 

WSGI介紹

WSGI(Web Server Gateway Interface)是一種規范,它定義了使用python編寫的web app(應用程序)與web server(socket服務端)之間接口格式,實現web app與web server間的解耦。

通俗的說:當規范建立后,程序就不再重復編寫web server(socket服務端),而是直接使用現成的實現WSGI的模塊(例如:wsgiref、uwsgi、werkzeug),從而讓程序員更加專注與業務代碼

與其重復造輪子,不如直接用現成的。

Python的wsgiref是基於WSGI規范封裝的模塊,我們可以在這個模塊基礎上開發我們的web server 

基於WSGI開發一個WEB服務器

# -*- coding:utf-8 -*-
# created by Alex Li - 路飛學城

from wsgiref.simple_server import make_server


def run_server(environ, start_response):
    """
    當有用戶在瀏覽器上訪問:http://127.0.0.1:8000/, 立即執行該函數並將函數的返回值返回給用戶瀏覽器
    :param environ: 請求相關內容,比如瀏覽器類型、版本、來源地址、url等
    :param start_response: 響應相關
    :return: 
    """

    start_response('200 OK',[('Content-Type', 'text/html;charset=utf-8')])
    return [bytes('<h1>我旁邊的這個人長的真丑呀!!',encoding='utf-8'),]

if __name__ == '__main__':
    httpd = make_server('localhost',8001,run_server)
    httpd.serve_forever()

 

別人家的網站和我們的網站  

你看別人的網站,可以根據URL不同看到不同的內容,比如這個:煎蛋網 

但我們剛才自己開發的網站,永遠只能看到同樣的內容。

 

怎么辦?我們自己也可以處理url呀

 1 # -*- coding:utf-8 -*-
 2 # created by Alex Li - 路飛學城
 3 
 4 from wsgiref.simple_server import make_server
 5 
 6 
 7 def western():
 8     return "歡迎來到歐美專區"
 9 
10 def japan():
11     return "歡迎來到日本人專區"
12 
13 
14 def routers():
15     """負責把url與對應的方法關聯起來"""
16     urlpatterns = (
17         ('/western/',western),
18         ('/japan/',japan),
19     )
20 
21     return urlpatterns
22 
23 
24 def run_server(environ, start_response):
25     """
26     當有用戶在瀏覽器上訪問:http://127.0.0.1:8000/, 立即執行該函數並將函數的返回值返回給用戶瀏覽器
27     :param environ: 請求相關內容,比如瀏覽器類型、版本、來源地址、url等
28     :param start_response: 響應相關
29     :return: 
30     """
31     start_response('200 OK',[('Content-Type', 'text/html;charset=utf-8')])
32     url = environ.get("PATH_INFO")
33     urlpatterns = routers()
34 
35     func = None
36 
37     for item in urlpatterns:
38         if item[0] == url:
39             func = item[1]
40             break
41     if func:
42         return [bytes(func(),encoding="utf-8"),]
43     else:
44         return [bytes('404 not found.',encoding="utf-8"),]
45 
46 if __name__ == '__main__':
47     httpd = make_server('localhost',8001,run_server)
48     httpd.serve_forever()
使你的wsgi web server支持多url

真棒,輕松的就可以使你的web server支持多頁面了。但你高興不起來,因為你看到人家別人的網站多姿多彩,各種圖片、各種動效,你的網站只能顯示文字。感覺像是上個世紀的產物,不刺激,哈,那就來點刺激的,讓你的網站也支持一下圖片和樣式。

# -*- coding:utf-8 -*-
# created by Alex Li - 路飛學城

from wsgiref.simple_server import make_server
import re ,os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))


def img_handler(url):
    img_relative_path  = re.sub("/static/","imgs/",url,count=1)
    img_path = os.path.join(BASE_DIR,img_relative_path)
    print('img',BASE_DIR,img_path)
    f = open(img_path,'rb')
    data = f.read()
    f.close()
    return data


def western():
    data = '''
    <h1>歡迎來到歐美專區</h1>

    <img src='/static/test_america.jpg' width='800px'/>

    '''

    return data


def japan():
    data = '''
    <h1>歡迎來到日本人專區</h1>
    
    <img src='/static/testimg.gif' />
    
    '''

    return data


def routers():
    """負責把url與對應的方法關聯起來"""
    urlpatterns = (
        ('/western/',western),
        ('/japan/',japan),
    )

    return urlpatterns


def run_server(environ, start_response):
    """
    當有用戶在瀏覽器上訪問:http://127.0.0.1:8000/, 立即執行該函數並將函數的返回值返回給用戶瀏覽器
    :param environ: 請求相關內容,比如瀏覽器類型、版本、來源地址、url等
    :param start_response: 響應相關
    :return: 
    """
    content_type = 'text/html;charset=utf-8'


    url = environ.get("PATH_INFO")
    urlpatterns = routers()

    func = None
    if url.startswith('/static/'): #代表是張圖片
        content_type = 'text/jpg;charset=utf-8'
        start_response('200 OK', [('Content-Type', content_type)])

        img_data = img_handler(url)
        return [img_data, ]

    else:
        for item in urlpatterns:
            if item[0] == url:
                func = item[1]
                break

    start_response('200 OK', [('Content-Type', content_type)])
    if func:
        return [bytes(func(),encoding="utf-8"),]
    else:
        return [bytes('404 not found.',encoding="utf-8"),]

if __name__ == '__main__':
    httpd = make_server('localhost',8001,run_server)
    httpd.serve_forever()
使自行開發的web server支持圖片

執行一下看看。 

 

真是技術改變生活呀!

 

能顯示圖片只是冰山一角,我們需要繼續開發一下功能:

  • 用戶表單提交,即:用戶向后台發送表單數據
  • 數據庫操作
  • 加載樣式和JS文件
  • 允許用戶下載文件

雖然自己開發有樂趣,但確實比較麻煩,在項目開發中,追求的更多是效率,而不是樂趣,所以還是盡量不要重復造輪子啦,我們接下來要學的Django框架就是幫我們已經造好的輪子。

Web框架的本質

雖然自己寫Web Server比較麻煩,但是我們從中也了解web框架的本質:

  1. 瀏覽器是socket客戶端,網站是socket服務端
  2. wsgi,是一個規范,wsgiref實現了這個規范並在其內部實現了socket服務端
  3. 根據 url 的不同執行不同函數,即:路由系統
  4. 函數,即:視圖函數
  5. 圖片、css、js文件 統一稱為靜態文件,需要讀取內容直接返回給用戶瀏覽器

Django來了

安裝

pip3 install django   #目前最新版本是2.0

* 注意,2.0 跟1.x版本上用法上是有些區別的,本課程我們主講2.x。 

安裝成功后,就會出現 django-admin 命令

創建Project

你想做個網站,首先我們要創建一個django project, 以后的代碼都放在這個項目里。

django-admin  startproject  mysite #項目名是mysite  

創建好的項目目錄結構

            mysite
            ├── manage.py		# 管理程序的文件,啟動和結束等。
            └── my site
                ├── __init__.py
                ├── settings.py		# 程序的配置文件
                ├── urls.py		# 程序的路由系統,即:url和處理其函數的對應的關系
                └── wsgi.py		# 指定框架的wsgi

	命令幫助我們創建了幾個文件,通過文件將功能代碼歸類。  

創建APP

一個項目中會包含一個或多個子項目,每個項目實現不同的功能和服務,如微信里包含基本通信功能,還有支付、小程序等,每塊業務都可以分為一個子項目。在django中, 我們管這個子項目叫app。下面是一個有多app的項目

 

為了開發和維護方便,每個子項目(app)都會有一個獨立文件夾來存放各自的業務代碼。
一般程序簡單情況下,只需要創建一個app即可。

python manage.py startapp app01   #app01 是app名稱

 

Django的第一次請求  

 

 

HTTP請求本質

上面的一次django請求都經歷了哪些過程呢?我們來剖析下

瀏覽器訪問網站的本質:socket客戶端、socket服務端之間的收發消息。

流程:

1. 【服務端】網站啟動,並監聽IP和端口,如:127.0.0.1:80,等待客戶端來連接…

2. 【客戶端】瀏覽器中輸入http://www.oldboyedu.com/index/,瀏覽器先后進行:

  1.   連接:域名解析得到網站IP,並根據端口進行連接。
  2.   發送消息:將請求數據發送給服務端,發送數據本質上是字符串,格式如下:
GET /index/ http1.1\r\nhost:www.luffycity.com…..\r\n\r\n
                              
POST /index/ http1.1\r\nhost:www.luffycity.com...\r\n\r\nage=18&num=1
3.

3. 【服務端】接收用戶請求發來的數據,並根據請求字符串解析,並做出響應。  

響應:HTTP/1.1 200 OK\r\nContent-Type: text/html;...\r\n\r\n<html>...</html>

4. 【客戶端】接收服務端響應的內容,將響應體展示在瀏覽器上,響應頭偷偷保存到瀏覽器。

5. 【客戶端】【服務端】連接斷開,Http請求終止(體現了Http短連接)。  

注意:請求和響應基本包含請求頭和請求體並通過\r\n\r\n進行分割。

 

用Django 開發用戶登錄頁面

用戶登錄是個表單啦,但目前我們只會用Django返回字符串,表單涉及的html元素比較多,總不能在view.py里寫好返回吧?這太low了,是的,怎么可以不low? 是時候表演真正的技術啦。

Django有個叫模板(Template)的東東,可以直接把你的Html代碼寫在模板里,返回給瀏覽器。

模板初探

想用模板僅需2步,

  1. 配置存html文件的模板目錄
  2. 在你的views.py的響應函數里返回對應的html文件 

 

 

是時候該講講套路啦 

剛才在開發用戶登錄頁面時,我們的請求處理流程是這樣的, 請求-> url.py -> views.py -> template -> 瀏覽器, 流程為什么這樣安排?中間如何要從數據庫里拿數據,是應該在哪個階段?其實Django或其它web語言的web框架在開發時都符合了某種神秘的套路,這個套路是什么?即MVC.

MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計創建 Web 應用程序的模式

不懂對不對?其實說白了,就是把Web開發中一個請求處理流程分成了3部分,每部分專注做自己的事。

  1. Model(模型)一般對應數據庫操作、紀錄的存取
  2. View(視圖)決定着如何展示數據
  3. Controller(控制器)負現處理用戶交互的部分。控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。

 

MVC & MTV 

Django是一個MTV框架,其架構模板看上去與傳統的MVC架構並沒有太大的區別。Django將MVC中的視圖進一步分解為 Django視圖 和 Django模板兩個部分,分別決定 “展現哪些數據” 和 “如何展現”,使得Django的模板可以根據需要隨時替換,而不僅僅限制於內置的模板。至於MVC控制器部分,由Django框架的URLconf來實現。

再具體點的圖

 

從下一章開始 ,我們會一點點把model,views,template,url 每個都延伸開來講。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM