Django系列(一):前期準備

一、web應用html

Web應用程序是一種能夠經過web訪問的應用程序,程序的最大好處是用戶很容易訪問應用程序,用戶只須要有瀏覽器便可,不須要再安裝其餘軟件。應用程序有兩種模式C/S、B/S。C/S是客戶端/服務器端程序,也就是說這類程序通常獨立運行。而B/S就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助谷歌,火狐等瀏覽器來運行。WEB應用程序通常是B/S模式。Web應用程序首先是「應用程序」,和用標準的程序語言,如java,python等編寫出來的程序沒有什麼本質上的不一樣。在網絡編程的意義下,瀏覽器是一個socket客戶端,服務器是一個socket服務端。java

以下代碼是一個python寫的服務端代碼,能夠用瀏覽器當客戶端去訪問該服務端,理解web服務:python

# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午8:37
# @Author  : Felix Wang

import socket

def handle_request(conn):
    request_data = conn.recv(1024)

    print("request_data: ", request_data)  # 觀察並分析request_data值
    conn.send("HTTP/1.1 200 OK\r\nstatus: 200\r\nContent-Type:text/html\r\n\r\n<h1>Hello, World!</h1>".encode("utf8"))
    # 響應首行\r\n響應頭(能夠有多個鍵值對,以\r\n分隔)\r\n\r\n響應體


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 8812))  # 綁定8812端口

    sock.listen(5)
    while True:
        print("the server is waiting for client-connection....")
        conn, addr = sock.accept()
        handle_request(conn)
        conn.close()


if __name__ == '__main__':
    main()

執行效果:mysql

二、http協議web

(1):協議簡介sql

HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於萬維網(WWW:World Wide Web)服務器與本地瀏覽器之間傳輸超文本的傳送協議。shell

HTTP是一個屬於應用層的面向對象的協議,因爲其簡捷、快速的方式,適用於分佈式超媒體信息系統。它於1990年提出,通過幾年的使用與發展,獲得不斷地完善和擴展。HTTP協議工做於客戶端-服務端架構上。瀏覽器做爲HTTP客戶端經過URL向HTTP服務端即WEB服務器發送全部請求。Web服務器根據接收到的請求,向客戶端發送響應信息。數據庫

 

 (2)、http協議特性django

a、基於TCP/IP編程

HTTP協議是基於TCP/IP協議上的應用層協議。

b、基於請求-響應模式

HTTP協議規定,請求從客戶端發出,最後服務器端響應該請求並返回。換句話說,確定是先從客戶端開始創建通訊的,服務器端在沒有接收到請求以前不會發送響應。

c、無狀態保存

HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議自身不對請求和響應之間的通訊狀態進行保存。也就是說在HTTP這個級別,協議對於發送過的請求或響應都不作持久化處理。

使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產生。協議自己並不保留以前一切的請求或響應報文的信息。這是爲了更快地處理大量事務,確保協議的可伸縮性,而特地把HTTP協議設計成如此簡單的。但是,隨着Web的不斷髮展,因無狀態而致使業務處理變得棘手的狀況增多了。好比,用戶登陸到一家購物網站,即便他跳轉到該站的其餘頁面後,也須要能繼續保持登陸狀態。針對這個實例,網站爲了可以掌握是誰送出的請求,須要保存用戶的狀態。HTTP/1.1雖然是無狀態協議,但爲了實現指望的保持狀態功能,因而引入了Cookie技術。有了Cookie再用HTTP協議通訊,就能夠管理狀態了。有關Cookie的詳細內容稍後講解。

 d、無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。

三、http請求協議與響應協議

http協議包含由瀏覽器發送數據到服務器須要遵循的請求協議與服務器發送數據到瀏覽器須要遵循的響應協議。用於HTTP協議交互的信被爲HTTP報文。請求端(客戶端)的HTTP報文作請求報文,響應端(服務器端)的作響應報文。HTTP報文自己是由多行數據構成的字符串文本。

(1):請求協議

請求格式,以下圖:

請求方式:get與post

 a、GET提交的數據會放在URL中的路徑以後,以?分割路徑和傳輸數據,參數之間以&相連,如EditBook?name=test&pwd=123;POST方法是把提交的數據放在HTTP包的請求體中;

 b、GET提交的數據大小有限制(由於瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制;

 c、GET與POST請求在服務端獲取請求數據方式不一樣;

示例:GET / HTTP/1.1\r\n Host: 127.0.0.1:8812\r\nUser-Agent: Mozilla/5.0...\r\n\r\n

 (2)響應協議

響應格式,以下圖:

示例:HTTP/1.1 200 OK\r\nstatus:200\r\nContent-Type:text/html\r\n\r\n<h1>Hello</h1>

響應狀態碼:狀態碼的職責是當客戶端向服務器端發送請求時, 描述返回的請求結果。藉助狀態碼,用戶能夠知道服務器端是正常處理了請求,仍是出現了錯誤。狀態碼(如:200 OK)以3位數字和緣由短語組成。數字中的第一位指定了響應類別,後兩位無分類。響應類別有如下5種:

(3)代碼實例

服務端:

# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午9:10
# @Author  : Felix Wang

import socket

sock = socket.socket()
sock.bind(("127.0.0.1", 8808))
sock.listen(5)

while 1:
    print("server waiting.....")
    conn, addr = sock.accept()
    data = conn.recv(1024)
    print("request-data", data)
    # 讀取html文件
    with open("login.html", "rb") as f:
        data = f.read()

    conn.send((b"HTTP/1.1 200 OK\r\n\r\n%s" % data))
    conn.close()

login.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
      用戶名 <input type="text" name="user">
      密碼 <input type="password" name="pwd">
      <input type="submit">
</form>
</body>
</html>

四、web框架

Web框架(Web framework)是一種開發框架,用來支持動態網站、網絡應用和網絡服務的開發。大多數的web框架提供了一套開發和部署網站的方式,也爲web行爲提供了一套通用的方法。web框架已經實現了不少功能,開發人員使用框架提供的方法而且完成本身的業務邏輯,就能快速開發web應用了。瀏覽器和服務器的是基於HTTP協議進行通訊的。也能夠說web框架就是在以上十幾行代碼基礎張擴展出來的,有不少簡單方便使用的方法,大大提升了開發的效率。

(1)、wsgire模塊

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

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

正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口協議來實現這樣的服務器軟件,讓咱們專心用Python編寫Web業務。這個接口就是WSGI:Web Server Gateway Interface。而wsgiref模塊就是python基於wsgi協議開發的服務模塊。

wsgire模塊使用詳解:

# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午9:21
# @Author  : Felix Wang
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 8080...')
# 開始監聽HTTP請求:
httpd.serve_forever()

總結:wsgiref模塊的主要做用是拆請求協議的包和封裝響應格式。

(2)本身搭建一個web框架

目錄結構:

# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午9:38
# @Author  : Felix Wang


import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='felixwang', db='mydb')
cur = conn.cursor()

sql = '''
    create table userinfo(
        id INT PRIMARY KEY,
        name VARCHAR(32),
        password VARCHAR(32)
)

'''
cur.execute(sql)

conn.commit()

cur.close()
conn.close()
models.py
# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午10:03
# @Author  : Felix Wang


import pymysql

from urllib.parse import parse_qs


def login(environ):
    if environ.get("REQUEST_METHOD") == "POST":

        try:
            request_body_size = int(environ.get('CONTENT_LENGTH', 0))
        except (ValueError):
            request_body_size = 0

        request_body = environ['wsgi.input'].read(request_body_size)
        data = parse_qs(request_body)

        user = data.get(b"user")[0].decode("utf8")
        pwd = data.get(b"pwd")[0].decode("utf8")

        # 鏈接數據庫
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='felixwang', db='mydb')
        # 建立遊標
        cur = conn.cursor()
        SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'" % (user, pwd)
        cur.execute(SQL)

        if cur.fetchone():
            f = open("templates/backend.html", "rb")
            data = f.read()
            data = data.decode("utf8")
            return data.encode("utf8")
        else:
            print("OK456")
            return b"user or pwd is wrong"

    else:
        f = open("templates/login.html", "rb")
        data = f.read()
        f.close()
        return data
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>welcome to myweb!</h4>
</body>
</html>
backend.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h4>登陸頁面</h4>
<form action="" method="post">
    用戶名 <input type="text" name="user">
    密碼 <input type="text" name="pwd">
    <input type="submit">
</form>

</body>
</html>
login.html
# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午9:38
# @Author  : Felix Wang

from wsgiref.simple_server import make_server
from app01.views import *
import urls


def routers():
    URLpattern = urls.URLpattern
    return URLpattern


def applications(environ, start_response):
    path = environ.get("PATH_INFO")
    start_response('200 OK', [('Content-Type', 'text/html'), ('Charset', 'utf8')])
    urlpattern = routers()
    func = None
    for item in urlpattern:
        if path == item[0]:
            func = item[1]
            break
    if func:
        return [func(environ)]
    else:
        return [b"<h1>404!<h1>"]


if __name__ == '__main__':
    server = make_server("", 8080, applications)
    print("Serving HTTP on port 8080...")
    server.serve_forever()
manage.py
# -*- coding: utf-8 -*-
# @Time    : 18-10-30 下午9:38
# @Author  : Felix Wang

from app01.views import *

URLpattern = (
    ("/login/", login),
)
urls.py

my_web這個package就是一個web框架,下載這個web框架就能夠快速實現一些簡單的web功能,好比頁面跳轉。

五、Django簡介

(1)、MVC與MTV模型

a、MVC

Web服務器開發領域裏著名的MVC模式,所謂MVC就是把Web應用分爲模型(M),控制器(C)和視圖(V)三層,他們之間以一種插件式的、鬆耦合的方式鏈接在一塊兒,模型負責業務對象與數據庫的映射(ORM),視圖負責與用戶的交互(頁面),控制器接受用戶的輸入調用模型和視圖完成用戶的請求,其示意圖以下所示:

b、MTV

Django的MTV模式本質上和MVC是同樣的,也是爲了各組件間保持鬆耦合關係,只是定義上有些許不一樣,Django的MTV分別是值:

  M 表明模型(Model): 負責業務對象和數據庫的關係映射(ORM)。  

  T 表明模板 (Template):負責如何把頁面展現給用戶(html)。

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

除了以上三層以外,還須要一個URL分發器,它的做用是將一個個URL的頁面請求分發給不一樣的View處理,View再調用相應的Model和Template,MTV的響應模式以下所示:

 

 通常是用戶經過瀏覽器向咱們的服務器發起一個請求(request),這個請求回去訪問視圖函數,(若是不涉及到數據調用,那麼這個時候視圖函數返回一個模板也就是一個網頁給用戶),視圖函數調用模型,模型去數據庫查找數據,而後逐級返回,視圖函數把返回的數據填充到模板中空格中,最後返回網頁給用戶。

 (2)、Django的下載與基本命令

a、下載django

pip install

b、建立一個django project (django-admin.exe所在的目錄要加入環境變量)

django-admin startproject mysite

注意:該命令在哪一個文件夾執行,django項目就建在了哪一個目錄下

 執行後生成mysite的工程,目錄結構以下:

manage.py -- Django項目裏面的工具,經過它能夠調用django shell和數據庫等。

settings.py -- 包含了項目的默認設置,包括數據庫信息,調試標誌以及其餘一些工做的變量。

urls.py -- 負責把URL模式映射到應用程序。

 c、在mysite目錄下建立應用(要先進入manage.py統計目錄)

python manage.py startapp blog

注意:一個項目中有多個應用,每一個應用都有本身的業務邏輯

執行後,mysite目錄下會生成blog這個應用,目錄以下:

 

d、啓動django項目(默認是8000)

python manage.py runserver 8000

這樣咱們的django就啓動起來了!當咱們訪問:http://127.0.0.1:8000/時就能夠看到:

(3)、基於Django實現簡單實例

urls文件(url控制器):

from django.contrib import admin
from django.urls import path
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index)
]

views文件(視圖):

from django.shortcuts import render

# Create your views here.
import datetime

def index(request):
    now = datetime.datetime.now()
    ctime = now.strftime("%Y-%m-%d %X")
    return render(request, "index.html", {"ctime": ctime})

index.html(模板文件):若沒有templates目錄則手動建立,其中放html文件

<!DOCTYPE html> 
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>  
</head>
<body>
  <h4>當前時間:{{ ctime }}</h4>
</body>
</html>

 

訪問效果:

注意:每個視圖函數都傳一個request形參,封裝了請求協議,並返回HttpResponse對象。

 

 六、補充

(1)、url的組成      

  協議://域名:端口號/路徑?參數(鍵值對,如:user=name&pwd=123)

       示例:https://www.baidu.com/s?wd=alex

(2)、Django框架問題

       用命令建立完成後沒有templates文件夾(存放html文件),須要手動建立,而且有些版本沒有配置templates路徑,需手動配置,方法以下:

       找到settings.py文件中的TEMPLATES列表中的 'DIRS': [os.path.join(BASE_DIR, "templates")]

(3)、當使用django時,若是頁面遇到forbidden錯誤時(post提交容易發生),就去settings.py文件中找到MIDDLEWARE列表的第3項'django.middleware.csrf.CsrfViewMiddleware',將其註釋掉便可。

相關文章
相關標籤/搜索