1. 程式人生 > >Django~1

Django~1

底層 必須 dea oca 目的 設置 ext gif gateway

一 什麽是web框架?

框架,即framwork,特指為解決一個開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來做表演。

對於所有的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。


最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。

如果要動態生成HTML,就需要把上述步驟自己來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,如果我們自己來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。

正確的做法是底層代碼由專門的服務器軟件實現,我們用Python專註於生成HTML文檔。因為我們不希望接觸到TCP連接、HTTP原始請求和響應格式,所以,需要一個統一的接口,讓我們專心用Python編寫Web業務。

這個接口就是WSGI:Web Server Gateway Interface。

-----------------------------Do a web framework ourselves---------------------------

step 1:

技術分享圖片
from wsgiref.simple_server import make_server


def application(environ, start_response): start_response(200 OK, [(Content-Type, text/html)]) return [b<h1>Hello, web!</h1>] httpd = make_server(‘‘, 8080, application) print(Serving HTTP on port 8000...) # 開始監聽HTTP請求: httpd.serve_forever()
View Code

註意:

技術分享圖片
整個application()函數本身沒有涉及到任何解析HTTP的部分,也就是說,底層代碼不需要我們自己編寫,
我們只負責在更高層次上考慮如何響應請求就可以了。

application()函數必須由WSGI服務器來調用。有很多符合WSGI規範的服務器,我們可以挑選一個來用。

Python內置了一個WSGI服務器,這個模塊叫wsgiref    
    
    
application()函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:

        
//environ:一個包含所有HTTP請求信息的dict對象; //start_response:一個發送HTTP響應的函數。 在application()函數中,調用: start_response(200 OK, [(Content-Type, text/html)]) 就發送了HTTP響應的Header,註意Header只能發送一次,也就是只能調用一次start_response()函數。 start_response()函數接收兩個參數,一個是HTTP響應碼,一個是一組list表示的HTTP Header,每 個Header用一個包含兩個str的tuple表示。 通常情況下,都應該把Content-Type頭發送給瀏覽器。其他很多常用的HTTP Header也應該發送。 然後,函數的返回值b<h1>Hello, web!</h1>將作為HTTP響應的Body發送給瀏覽器。 有了WSGI,我們關心的就是如何從environ這個dict對象拿到HTTP請求信息,然後構造HTML, 通過start_response()發送Header,最後返回Body。
View Code

step2:

技術分享圖片
print(environ[PATH_INFO])
    path=environ[PATH_INFO]
    start_response(200 OK, [(Content-Type, text/html)])
    f1=open("index1.html","rb")
    data1=f1.read()
    f2=open("index2.html","rb")
    data2=f2.read()

    if path=="/yuan":
        return [data1]
    elif path=="/alex":
        return [data2]
    else:
        return ["<h1>404</h1>".encode(utf8)]
View Code

step3:

技術分享圖片
from wsgiref.simple_server import make_server

def f1():
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2():
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

def application(environ, start_response):

    print(environ[PATH_INFO])
    path=environ[PATH_INFO]
    start_response(200 OK, [(Content-Type, text/html)])


    if path=="/yuan":
        return f1()

    elif path=="/alex":
        return f2()

    else:
        return ["<h1>404</h1>".encode("utf8")]


httpd = make_server(‘‘, 8502, application)

print(Serving HTTP on port 8084...)

# 開始監聽HTTP請求:
httpd.serve_forever()
View Code

step4:

技術分享圖片
from wsgiref.simple_server import make_server


def f1(req):
    print(req)
    print(req["QUERY_STRING"])

    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2(req):

    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

import time

def f3(req):        #模版以及數據庫

    f3=open("index3.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
    data3=str(data3,"utf8").replace("!time!",str(times))


    return [data3.encode("utf8")]


def routers():

    urlpatterns = (
        (/yuan,f1),
        (/alex,f2),
        ("/cur_time",f3)
    )
    return urlpatterns


def application(environ, start_response):

    print(environ[PATH_INFO])
    path=environ[PATH_INFO]
    start_response(200 OK, [(Content-Type, text/html)])


    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server(‘‘, 8518, application)

print(Serving HTTP on port 8084...)

# 開始監聽HTTP請求:

httpd.serve_forever()
View Code

夥計們,不知不覺我們自己已經寫出一個web框架啦!

二 MVC和MTV模式

著名的MVC模式:所謂MVC就是把web應用分為模型(M),控制器(C),視圖(V)三層;他們之間以一種插件似的,松耦合的方式連接在一起。

模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。

技術分享圖片

Django的MTV模式本質上與MVC模式沒有什麽差別,也是各組件之間為了保持松耦合關系,只是定義上有些許不同,Django的MTV分別代表:

Model(模型):負責業務對象與數據庫的對象(ORM)

Template(模版):負責如何把頁面展示給用戶

View(視圖):負責業務邏輯,並在適當的時候調用Model和Template

此外,Django還有一個url分發器,它的作用是將一個個URL的頁面請求分發給不同的view處理,view再調用相應的Model和Template

技術分享圖片

三 django的流程和命令行工具

django實現流程

技術分享圖片
django
    #安裝: pip3 install django

          添加環境變量

    #1  創建project
       django-admin startproject mysite

       ---mysite

          ---settings.py
          ---url.py
          ---wsgi.py

       ---- manage.py(啟動文件)  

    #2  創建APP       
       python mannage.py startapp  app01

    #3  settings配置
    
       TEMPLATES

       STATICFILES_DIRS=(
            os.path.join(BASE_DIR,"statics"),
        )

       STATIC_URL = /static/ 
       #  我們只能用 STATIC_URL,但STATIC_URL會按著你的STATICFILES_DIRS去找#4  根據需求設計代碼
           url.py
           view.py

    #5  使用模版
       render(req,"index.html")   

    #6  啟動項目
       python manage.py runserver  127.0.0.1:8090

    #7  連接數據庫,操作數據
       model.py
View Code

django的命令行工具

django-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每一個Django Project裏都會有一個mannage.py。

<1> 創建一個django工程 : django-admin.py startproject mysite

當前目錄下會生成mysite的工程,目錄結構如下:

技術分享圖片

  • manage.py ----- Django項目裏面的工具,通過它可以調用django shell和數據庫等。
  • settings.py ---- 包含了項目的默認設置,包括數據庫信息,調試標誌以及其他一些工作的變量。
  • urls.py ----- 負責把URL模式映射到應用程序。

<2>在mysite目錄下創建blog應用: python manage.py startapp blog

技術分享圖片

<3>啟動django項目:python manage.py runserver 8080

這樣我們的django就啟動起來了!當我們訪問:http://127.0.0.1:8080/時就可以看到:

技術分享圖片

<4>生成同步數據庫的腳本:python manage.py makemigrations

同步數據庫: python manage.py migrate

註意:在開發過程中,數據庫同步誤操作之後,難免會遇到後面不能同步成功的情況,解決這個問題的一個簡單粗暴方法是把migrations目錄下

的腳本(除__init__.py之外)全部刪掉,再把數據庫刪掉之後創建一個新的數據庫,數據庫同步操作再重新做一遍。

<5>當我們訪問http://127.0.0.1:8080/admin/時,會出現:

技術分享圖片

所以我們需要為進入這個項目的後臺創建超級管理員:python manage.py createsuperuser設置好用戶名和密碼後便可登錄啦!

<6>清空數據庫:python manage.py flush

<7>查詢某個命令的詳細信息: django-admin.py help startapp

admin 是Django 自帶的一個後臺數據庫管理系統。

<8>啟動交互界面 :python manage.py shell

這個命令和直接運行 python 進入 shell 的區別是:你可以在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操作數據,還有一些小測試非常方便。

<9> 終端上輸入python manage.py 可以看到詳細的列表,在忘記子名稱的時候特別有用


實例練習1-提交數據並展示

技術分享圖片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>創建個人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性別<input type="text" name="sex"></p>
    <p>郵箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性別</td>
        <td>郵箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


-----------------------url.py---------------------------------------
url(r^userInfor/, views.userInfor)

-----------------------views.py--------------------------------------

info_list=[]

def userInfor(req):

    if req.method=="POST":
        username=req.POST.get("username",None)
        sex=req.POST.get("sex",None)
        email=req.POST.get("email",None)

        info={"username":username,"sex":sex,"email":email}
        info_list.append(info)

    return render(req,"userInfor.html",{"info_list":info_list})
View Code

實例練習2-提交數據並展示(數據庫)

技術分享圖片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>創建個人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性別<input type="text" name="sex"></p>
    <p>郵箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性別</td>
        <td>郵箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


----------------------------------------------models.py
from django.db import models

# Create your models here.


class UserInfor(models.Model):

    username=models.CharField(max_length=64)
    sex=models.CharField(max_length=64)
    email=models.CharField(max_length=64)

----------------------------------------------views.py

from django.shortcuts import render

from app01 import models
# Create your views here.


def userInfor(req):

    if req.method=="POST":
        u=req.POST.get("username",None)
        s=req.POST.get("sex",None)
        e=req.POST.get("email",None)


       #---------表中插入數據方式一
            # info={"username":u,"sex":e,"email":e}
            # models.UserInfor.objects.create(**info)

       #---------表中插入數據方式二
        models.UserInfor.objects.create(
            username=u,
            sex=s,
            email=e
        )

        info_list=models.UserInfor.objects.all()

        return render(req,"userInfor.html",{"info_list":info_list})

    return render(req,"userInfor.html")
View Code

Django~1