python之Djiango框架簡介

基礎css

# HTTP響應狀態碼
    10X:服務端已經接受到你的數據了 你能夠繼續提交數據進行下一步操做
    20X:請求成功(200)
    30X:重定向(301,302)
    40X:請求錯誤(404)
    50X:服務端錯誤(500)

# GET請求與POST請求
        GET請求:獲取頁面資源
        POST請求:朝服務端發送數據(讓服務端校驗該數據)

1、Web框架本質html

  全部的Web應用本質上就是一個socket服務端,而用戶的瀏覽器就是一個socket客戶端前端

 

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

  能夠寫幾個簡單頁面,而後經過http://127.0.0.1:8080/頁面名稱  來訪問對應的頁面測試mysql

import socket

server = socket.socket()  # 默認是TCP協議
server.bind(('127.0.0.1',8080))  # 綁定IP端口
server.listen(5)  # 監聽 半連接池:保護計算機安全

while True:
    conn, addr = server.accept()   # 等待鏈接
    data = conn.recv(1024)         # 接收客戶端信息
    # 遵循HTTP協議,給迴應的消息加上響應狀態行
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    res = data.decode('utf-8')
    current_path = res.split('\r\n')[0].split(' ')[1]  # 字符串切割,獲取路徑
    # print(current_path)
    # 根據不一樣的路徑返回不一樣的內容
    if current_path == '/index':
        # conn.send(b'index')
        with open('templates/111.html','rb') as f:
            conn.send(f.read())
    elif current_path == '/login':
        conn.send(b'login')
    else:
        conn.send(b'404')
    conn.close()

瀏覽器訪問頁面請求信息:jquery

  HTTP協議主要規定了客戶端和服務器之間的通訊格式nginx

  響應相關信息能夠在瀏覽器調試窗口的network標籤頁中看到。能夠根據view信息切割得到須要請求的頁面web

請求首行
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.142 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
Cookie: csrftoken=3vPenhmlRQb8Tvl4okwYM0OZpDCl3P7rbxvfpRDOHJy1zUApw89ugxM6OZSxhIBM\r\n
\r\n
請求體
'
http://127.0.0.1:8080/index
view展開:

根據不一樣的路徑返回不一樣頁面請求---函數版sql

import socket

sk = socket.socket()
sk.bind(('127.0.0.1',8001))
sk.listen()

# 將不一樣的內容部分封裝成函數
def index(url):
    # 讀取index.html頁面內容
    with open("index.html",'rb',encoding="utf-8") as f:
        s = f.read()
    # 返回字節數據
    return bytes(s,encoding="utf-8")

def login(url):
    with open("login.html",'rb',encoding="utf-8") as f:
        s = f.read()
    return bytes(s, encoding="utf-8")

list1= [
    ("templates/111.html","/index"),
    ("templates/login.html",'/login'),
]

while True:
    # 等待鏈接
    conn,add = sk.accept()
    data = conn.recv(1024) # 接收客戶端發來的消息
    # 從data 中獲取路徑
    data = str(data,encoding='utf-8') # 把收到的字節類型數據轉換成字符串
    print("data>>>",data)
    # 按\r\n切割,url是從瀏覽器發過來的消息中分離出來的訪問路徑
    url = data.split("\r\n")[0].split(' ')[1]
    print("url>>>>",url)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n') #遵循http協議,因此回覆的消息也要加狀態行
    # 根據不一樣的路徑返回不一樣內容,reponse是具體的響應體
    func = None
    for i in list1:
        if i[0].split("/")[1] == url:
            func = i[1]
            break
    # print("func>>>",func)
    if func:
        reponse = func(url)
    else:
        reponse = b"404 not found!"

    conn.send(reponse)
    conn.close()

# 還有點問題//TODO
View Code

 2、服務器程序和應用程序 數據庫

  對於真實開發中的python web程序來講,通常會分爲兩部分:服務器程序和應用程序。
  服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的各類數據進行整理。

  應用程序則負責具體的邏輯處理。爲了方便應用程序的開發,就出現了衆多的Web框架,例如:Django、Flask、web.py等。不一樣的框架有不一樣的開發方式,可是不管如何,開發出的應用程序都要和服務器程序配合,才能爲用戶提供服務。

  WSGI(Web Server Gateway Interface)就是一種規範,它定義了使用Python編寫的web應用程序與web服務器程序之間的接口格式,實現web應用程序與web服務器程序間的解耦

  經常使用的WSGI服務器有uwsgi、Gunicorn。而Python標準庫提供的獨立WSGI服務器叫wsgiref,Django開發環境用的就是這個模塊來作服務器。

1.wsgiref 模塊

  利用wsgiref模塊來替換咱們本身寫的web框架的socket server部分

# 未拆分前代碼
# http://127.0.0.1/index訪問對應的名稱到對應的頁面
from wsgiref.simple_server import make_server

def index():
    return 'index'

def reg():
    return 'res'

def login():
    return 'login'

def error():
    return '404'

urls = [
    ('/index',index),
    ('/reg',reg),
    ('/login',login),
]

def run(env,reponse):
    reponse('200 OK', [])  # 固定格式
    print(env)  # 將http格式的數據處理完畢,造成一個字段給你調用
    current_path = env.get('PATH_INFO')
    # if current_path == '/index':
    #     return [b'index']
    func = None
    for url_tuple in urls:
        if current_path == url_tuple[0]:
            func = url_tuple[1]   # 若是路由匹配上了,就回去對應的函數
            break
    if func:
        res = func()
    else:
        res = error()
    return [res.encode('utf-8')]

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run)  # 一直監聽地址,只要有請求,就會給最後的函數或對象調用:run()執行
    server.serve_forever()
# urls.py 存放訪問連接後的頁面

from views import *
urls = [
    ('/index',index),
    ('/reg',reg),
    ('/login',login),
]


# views.py 存放訪問頁面函數
def index():
    return 'index'

def reg():
    return 'res'

def login():
    return 'login'

def error():
    return '404'

# wsgiref.py存放啓動
from wsgiref.simple_server import make_server
from urls import urls
from views import *

def run(env,response):
    response('200 OK', [])  # 固定格式 不需掌握
    print(env)  # 將http格式的數據處理完畢 造成一個字段給你調用
    current_path = env.get('PATH_INFO')
    func = None
    for url_tuple in urls:
        if current_path == url_tuple[0]:
            func = url_tuple[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()
拆分後代碼

根據拆分後的代碼,若是須要再添加訪問頁面,只須要在urls.py(路由與視圖函數的映射關係)和views.py(視圖函數)中增長對應的連接和函數就能夠

2.動靜態頁面

  靜態網頁:數據是寫死的,一直不變

  動態網頁:數據實時獲取的,一直在改變(eg:數據庫的數據或當前時間)

2.1獲取時間並顯示在頁面上:

# 在上面拆分代碼的基礎上
# urls.py增長
urls = [
    ('/index',index),
    ('/reg',reg),
    ('/login',login),
    ('/get_time',get_time),
]

# 對象視圖views.py裏增長函數
import time
def get_time():
    with open('templates/show_time.html','r',encoding='utf-8') as f:
        data = f.read()
    current_time = time.strftime('%Y-%m-%d %X')
    res = data.replace('timekkk',current_time)  # 字符串替換
    return res

而後運行wsgiref.py就能夠看到頁面上顯示動態的時間了,每次刷新時間都會變化

2.2 給前端傳字典而且字典能夠取值

# urls.py中新增對應訪問路徑
from view2 import *

urls2 = [
    ('/index', index),
    ('/reg', reg),
    ('/login', login),
    ('/get_time', get_time),
    ('/get_user', get_user),
]

# views.py中新增對應函數
from jinja2 import Template

def get_user(env):
    user_dict = {'username': 'simon', 'password': '123'}
    with open('templates/get_user.html', 'r', encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)  # 實例化產生對象
    res = tmp.render(data=user_dict)  # 將user_dict傳遞給前端頁面,前端頁面用過變量名data就可以拿到user_dict字典
    return res

# html頁面body中設置
{#傳data這裏就寫data#}
{{ data }}
{#獲取帳號密碼#}
<p>{{data.username}}</p>
<p>{{data['password']}}</p>
<p>{{data.hobby.0}}</p>
<p>{{data.hobby.1}}</p>

模板渲染(雛形)

  後端產生的數據直接傳遞給前端頁面,前端頁面獲取數據經過模板語法展現

模板語法:

  {{}} 獲取後端傳遞的數據,經過變量名(變量名相關的)

  {%%} 與邏輯相關的使用這個語法

  jinja2模板語法極爲接近後端python語法

{{ data }}
<p>{{data.username}}</p>
<p>{{data['password']}}</p>
<p>{{data.hobby.0}}</p>
<p>{{data.hobby.1}}</p>
 

 

邏輯相關:

{%for user_dict in user_list%}
<tr>
<td>{{user_dict.id}}</td>
<td>{{user_dict.username}}</td>
<td>{{user_dict.password}}</td>
</tr>
{%endfor%}

2.3 數據庫取值頁面顯示

#urls2.py
from view2 import *

urls2 = [
    ('/get_data',get_data),
]

# view2.py 新增函數
from jinja2 import Template
import pymysql

def get_data(env):
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = '123',
        database = 'test',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    cursor.execute('select * from userinfo')
    res = cursor.fetchall()
    with open('templates/get_data.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res1 = tmp.render(user_list = res)
    return res1

# simple_server.py模塊,和以前的沒什麼變化
from wsgiref.simple_server import make_server
from urls2 import urls2
from view2 import *

def run(env,reponse):
    reponse('200 OK', [])  # 固定格式
    print(env)  # 將http格式的數據處理完畢,造成一個字段給你調用
    current_path = env.get('PATH_INFO')
    # if current_path == '/index':
    #     return [b'index']
    func = None
    for url_tuple in urls2:
        if current_path == url_tuple[0]:
            func = url_tuple[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)  # 一直監聽地址,只要有請求,就會給最後的函數或對象調用:run()執行
    server.serve_forever()

# get_data.html前端頁面代碼
# body內容
<table>
    <thead>
        <tr>
            <th>id</th>
            <th>username</th>
            <th>password</th>
        </tr>
    </thead>
    <tbody>
        {%for user_dict in user_list%}
            <tr>
                <td>{{user_dict.id}}</td>
                <td>{{user_dict.username}}</td>
                <td>{{user_dict.password}}</td>
            </tr>
        {%endfor%}
    </tbody>
</table>
數據庫取值

2.4 web服務渲染流程

  根據早上的流程,咱們能夠劃出下面這個圖

2.5 web框架

python主流三大框架:

   a.socket服務

   b:路由與視圖函數映射關係

   c:模板渲染
  django:大而全 相似航空母艦

     a.用的別人的 wsgiref 上線以後會換成uwsgi;默認併發1000多,本身能夠加nginx之類處理

     b.本身寫的

     c.本身寫的
  flask:小而精,輕量級框架

  a用的別人的  werkzeug  
  b本身寫的
  c用的別人 jinja2
  tornado:異步非阻塞

    三者都是本身寫的

3、Django簡介

1.Django安裝與注意事項

# 主意事項
    1.計算機名稱不能含有中文
    2.一個pycharm窗口就是一個工程(項目)
    3.項目文件夾不要有中文

# ps:django版本: django 1.X(如今用的版本是這個1.11.11)

# 安裝
    pip3 install django
# 或pycharm直接安裝,能夠指定版本specify version
# 若是已經安裝了高版本須要下降版本:pip3 uninstall django,而後從新指定安裝:pip3 install django ===1.11.20 或pycharm指定版本安裝 # 查看djiango是否安裝成功 命令行界面:django-admin # 命令行建立django項目 django-admin startproject 項目名 ps:建立一個應用面的文件夾,裏面有一個跟應用名同名的文件夾和一個manage.py的文件 # 命令行建立應用 django-admin startapp 應用名 # application 一個django項目 能夠有多個應用,django是一款開發應用的web框架 django項目就相似是一所大學,而裏面的應用就相似於一個個學院 # 命令行啓動項目 python manage.py runserver 啓動成功後瀏覽器能夠訪問:http://127.0.0.1:8000和http://127.0.0.1:8000/admin ps:命令行建立django項目不會自動新建templates文件夾,而且settings.py配置文件(TEMPLATES 列表中DIRS)不會自動寫templates文件夾路徑,因此都須要手動添加[os.path.join(BASE_DIR,'templates')]
以下圖:
# pycharm建立 項目:File-->New Project-->Django-->Location(建立項目)-->More Settings建立應用--->Application name:應用名 在pycharm的命令行中建立應用:Tools-->Run manage.py TASK-->startapp 應用名 應用建立後須要再settings.py中註冊應用INSTALLED_APPS裏添加 啓動後能夠訪問:http://127.0.0.1:8000 # 注意: 1 在django中建立的應用必須去settings文件中註冊才能生效,不然django不識別 2 確保不要端口衝突

2.Django項目目錄結構

項目名
    應用名文件夾
        migrations文件夾
            數據庫遷移記錄
        admin.py
            django admin後臺管理相關
        models.py
            模型類
        views.py
            視圖函數
        
    項目同名文件夾
        settings.py
            django暴露給用戶可配置的配置文件
        urls.py
            路由與視圖函數映射關係
    templates
        全部的html文件
    manage.py
        django入口文件

3.Django 必會三板斧

# django小白必會三板斧

# HttpResponse:返回字符串
# views.py
def index(request):
    return HttpResponse("Hello Django index")
    
# render:返回html頁面
def login(request):
    return render(request,'login.html')
    
# redirect:重定向
def home(request):
    return redirect('https://www.baidu.com')

# urls.py配置文件中加對應訪問路徑
from django.contrib import admin
from django.urls import path
from app01 import views

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

4.靜態文件配置

# 動態實時監測到前綴的變化
login.html
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
    {% load static %}
    <link href="{% static 'bootstrap-3.3.7/css/bootstrap.min.css' %}" rel="stylesheet">
    <script src={% static "bootstrap-3.3.7/js/bootstrap.min.js" %}></script>
    
</head>

#用上述方法settings.py中接口前綴隨便修改,也不須要修改html中的對應前綴

# settings.py
# 接口前綴:要想訪問靜態資源必須static打頭:
#     <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
STATIC_URL = '/static/'
# 新增文件放置路徑
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
    os.path.join(BASE_DIR,'static1'),
    os.path.join(BASE_DIR,'static2'),
]

例:登陸功能簡單實現

# form表單默認是get請求
    get請求攜帶的參數是拼接在url後面的以?開頭&連接,默認method方式爲Get
    ps:get請求能夠攜帶參數 可是參數的大小有限制 最大4KB,而且是明文的
    http://127.0.0.1:8000/login/?username=simon&password=123

# 若是改成method改成post提交,須要將settings.py中一行註釋,不然會報403錯誤:
# 'django.middleware.csrf.CsrfViewMiddleware', # 跨站請求僞造

獲取用戶輸入的框 都必需要有name屬性

action參數有三種寫法
    1.什麼都不寫 默認往當前頁面的url地址提交
    2.只寫路由後綴(******)
    <form action="/login/" method="post">
    3.寫全路徑
        <form action="https://www.baidu.com" method="post"> 
# 數據後端獲取

#前端
            <form action="" method="post">
                <p>username:<input type="text" class="form-control" name="username"></p>
                <p>password:<input type="password" class="form-control" name="password"></p>
                <p>籃球<input type="checkbox" name="xxx" value="basketball"></p>
                <p>足球<input type="checkbox" name="xxx" value="football"></p>
                <p>冰球<input type="checkbox" name="xxx" value="ice"></p>
                <input type="submit" class="btn btn-success pull-right">
            </form>
# views.py:獲取訪問login頁面的method以及post提交的數據
def login(request):
    print(request.method) # 獲取當前請求方式
    if request.method == 'POST':
        # 獲取post請求提交的數據
        print(request.POST)
        # get請求默認拿列表最後一個值:如-獲取到2個username,取值永遠拿最後一個元素
        username = request.POST.get('username')
        password = request.POST.get('password')  # 還能夠在後面增長判斷帳號密碼判斷,之後經過數據庫來判斷傳遞的帳號密碼
     if username == "simon" and password == "123":
      return redirect("http://www.xiaohuar.com")
     return "xxxxxxx" hobby
= request.POST.getlist('xxx') print(hobby,type(hobby)) print(username,type(username)) print(password, type(password)) return render(request,'login.html') # 結果: POST <QueryDict: {'username': ['simon'], 'password': ['123'], 'xxx': ['basketball', 'football', 'ice']}> ['basketball', 'football', 'ice'] <class 'list'> simon <class 'str'> 123 <class 'str'>
相關文章
相關標籤/搜索