Django框架簡介(1)

手寫web框架

# coding:utf8

import socket

server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)

# data 中的信息
"""
請求首行,代表請求方式以及遵循的http協議版本
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/78.0.3904.97 Safari/537.36\r\n
Sec-Fetch-User: ?1\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
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=aOZSalMQkKGbzstfjcw3O9sDoegdywL8AD7PzhidAyx3tXShN7oQtxN1MMnS6GVX\r\n
\r\n(******)
請求體

'
"""
while True:
    conn, addr = server.accept()  # 阻塞態
    data = conn.recv(1024)
    # print(data)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    data_str = data.decode('utf-8')
    current_path = data_str.split('\r\n')[0].split(' ')[1]
    print(current_path)
    if current_path == '/index':
        # conn.send(b'index')
        with open(r'01 純手擼的前端頁面.html','rb') as f: # 基於網絡傳輸,因此用'rb'
            conn.send(f.read())
    elif current_path == '/login':
        conn.send(b'login')
    else:
        conn.send(b'404 error')
    conn.close()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
    <h1>你好呀,大兄弟!</h1>
        <img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2973069531,657782944&fm=26&gp=0.jpg" alt="圖片不存在!">

</body>
</html>

基於wsgiref模塊寫web服務端框架

基於第三方模塊寫web:
views.py 裏面的放的是函數 咱們管這些函數叫視圖函數 視圖層
urls.py 裏面放的是 路由(後綴)與視圖函數的對應關係 路由層
templates文件夾 裏面放的全是html文件html

# 服務端web框架文件

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

def run(env,response):
    """
    :param env: 請求相關的全部數據 將http數據所有提早處理成了字典的形式 供調用者使用
    :param response: 響應相關的全部數據
    :return: 給前端真正的數據
    """
    # print(env)
    response('200 OK',[('xxx','liu'),])
    current_path = env.get('PATH_INFO')
    # print(current_path)
    # if current_path == '/index':
    #     return [b'index']
    # elif current_path == '/login':
    #     return [b'login']
    # 定義一個存儲函數名的標誌位
    func = None
    for url in urls:  # url =  ('/login',login)  ('/index',index)
        if current_path == url[0]:  # 用戶敲的後綴名 你後端有對應的處理業務
            func = url[1]  # 將匹配上的函數名賦值給func變量
            break  # 一旦用戶匹配上了對應的業務接口 馬上結束匹配
    # 判斷func是否被賦值
    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)  # 實時監聽本機8080端口
    # 一旦有請求來了 會統一交給run函數處理(調用run函數並傳參run(env,response))
    server.serve_forever()  # 啓動服務端
<!--templates文件夾中的html文件-->
# xxx.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<h1>我是xxx頁面</h1>
</body>
</html>

# get_time.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
sadadadasdsadsad
</body>
</html>
# get_user.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ userDic }}</p>
<p>{{ userDic.username }}</p>
<p>{{ userDic['age'] }}</p>
<p>{{ userDic.get('hobby') }}</p>
<p>{{ userDic.get('hobby').0 }}</p>
<p>{{ userDic.get('hobby').1 }}</p>
<p>{{ userDic.get('hobby').2 }}</p>
</body>
</html>

# get_data.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h2 class="text-center">數據展現</h2>
            <table class="table table-striped table-bordered table-hover">
                <thead>
                    <tr>
                        <th>idd</th>
                        <th>name</th>
                        <th>sex</th>
                        <th>age</th>
                        <th>hire_date</th>
                        <th>post</th>
                        <th>post_comment</th>
                        <th>salary</th>
                        <th>office</th>
                        <th>depart_id</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user_dic in user_list %}
                        <tr>
                            <td>{{ user_dic.idd }}</td>
                            <td>{{ user_dic.name }}</td>
                            <td>{{ user_dic.sex }}</td>
                            <td>{{ user_dic.age }}</td>
                            <td>{{ user_dic.hire_date}}</td>
                            <td>{{ user_dic.post }}</td>
                            <td>{{ user_dic.post_comment }}</td>
                            <td>{{ user_dic.salary }}</td>
                            <td>{{ user_dic.office }}</td>
                            <td>{{ user_dic.depart_id }}</td>
                        </tr>
                    {% endfor %}
                </tbody>

            </table>
        </div>
    </div>
</div>
</body>
</html>
# view.py 文件

def login(env):
    return 'login'

def index(env):
    return 'index'

def reg(env):
    return 'reg'

def xxx(env):
    # return 'xxx'
    with open(r'G:\Python代碼平常\day051 django\templates/xxl.html','r',encoding='utf-8') as f:
        return f.read()

def error(env):
    return '404 error'


import time
def get_time(env):
    ctime = time.strftime('%Y-%m-%d %X')
    # 後端數據 如何傳遞給html頁面(利用字符串的替換)
    with open(r'G:\Python代碼平常\day051 django\templates/get_time.html','r',encoding='utf-8') as f:
        data = f.read()
    data = data.replace('sadadadasdsadsad',ctime)
    return data


from jinja2 import Template
def get_userdict(env):
    user_dic = {'username':'jason','age':18,'hobby':['read','book','run']}
    with open(r'G:\Python代碼平常\day051 django\templates/get_user.html','r',encoding='utf-8') as f:
        data = f.read()
    temp = Template(data)
    res = temp.render(userDic = user_dic)  # 將user_dic傳遞給html頁面 頁面上經過userDic就可以拿到後端傳遞過來的值
    return res

import pymysql
def get_data(env):
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = '123',
        db = 'db3',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)  # 將查出來的數據組織成一個字典
    sql = "select * from userinfo"  # 關鍵性的數據 不要本身手動拼接
    affect_rows = cursor.execute(sql)  # sql注入:就是利用MySQL註釋語法
    # print(affect_rows)
    user_list = cursor.fetchall()
    # print(user_list)
    # return 'hahahahha'
    with open(r'G:\Python代碼平常\day051 django\templates/get_data.html','r',encoding='utf-8') as f:
        data = f.read()
    temp = Template(data)
    res = temp.render(user_list = user_list)
    return res
# urls.py

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

動靜態網頁
靜態網頁
數據是寫死的 萬年不變(哪怕改變了 也是人爲直接修改)
動態網頁
數據是實時獲取的
eg:
1 後端代碼動態獲取 當前時間
2 數據是從數據庫查詢出來的前端

題目1
        訪問頁面 頁面上展現當前訪問的時間
    
    題目2
        訪問頁面 頁面上展現後端用戶字典 而且在前端頁面上能夠
        利用一些簡便的方式操做字典取值
        
jinja2模板語法
    專門用來處理後端數據與html頁面的交互
    
    模板語法(極其貼近python後端語法)  
        讓你可以在html頁面上 也可以用後端python語法來操做後端傳遞過來的數據
    <p>{{ userDic }}</p>
    <p>{{ userDic.username }}</p>
    <p>{{ userDic['age'] }}</p>
    <p>{{ userDic.get('hobby') }}</p>
    <p>{{ userDic.get('hobby').0 }}</p>
    <p>{{ userDic.get('hobby').1 }}</p>
    <p>{{ userDic.get('hobby').2 }}</p>
    
    {% for user_dic in user_list %}
        <tr>
            <td>{{ user_dic.id }}</td>
            <td>{{ user_dic.username }}</td>
            <td>{{ user_dic.password }}</td>
        </tr>
    {% endfor %}
基於jinja2模板語法 實現後端給html頁面傳值
        模板語法是在後端生效的 瀏覽器是沒法識別模板語法
        全部的數據渲染全都是在後端事先生成好的 而後將完整的html頁面丟給瀏覽器
        {{ user_dic }}
        {%for i in user_list%}
        {%endfor%}
        變量相關  {{}}
        邏輯相關  {%%}

{# #} 模板語法的註釋,該語法註釋以後,前端是看不到的,而原生的html的語法註釋<!-- 電話費的-->前端能夠看到,注意區別。

python三大主流框架

django 大而全 自帶的組件和功能很是很是多 相似於航空母艦
不足之處:寫小項目的時候 可能會比較笨重(大材小用)python

flask 小而精 短小精悍 自帶的組件和功能特別特別少 相似於遊騎兵
基本所有依賴於第三方組件
不足之處:受限於第三方模塊的影響比較大
若是將flask全部第三方模塊加起來 可以直接蓋過djangomysql

tornado 異步非阻塞 這個框架甚至能夠用來開發遊戲服務器jquery

a:socket部分
b:路由匹配
c:模板語法web

django:
a用的別人的wsgiref(django默認的)
b本身寫的
c本身寫的
flask:
a用的別人的werkzeug
b本身寫的
c用的別人的jinja2
Tornado:
a,b,c都是本身寫的sql

django框架介紹

注意事項

*1.計算機名稱不能有中文
        2.python解釋器不要使用3.7版本  推薦使用版本3.4~3.6,對Django兼容性比較好
        3.一個pycharm窗口 只能跑一個項目,項目名不要有中文*

        django版本問題
                django版本以1.11.11爲主(1.11.9~1.11.13)

django下載方法

方式一:pycharm settings中安裝數據庫

方式二:cmd安裝django

pip3 install django==1.11.11

如何檢驗django是否安裝成功:
        命令行敲 django-admin

django項目及app的建立

命令行建立項目

1.建立django項目

​ django-admin startproject 項目名(例如mysite)

2.啓動django項目

​ 切換到項目文件夾下
​ python3 manage.py runserver
​ python3 manage.py runserver 127.0.0.1:8080

3.中止項目
ctrl+c

4.建立應用(django支持多app開發)

​ python3 manage.py startapp app01

注意:
1.命令行建立不會自動建立templates文件夾
2.配置文件中不會自動幫你書寫templates文件路徑

pycharm建立項目

​ 方法一:FILE>>>new project 選擇第二個Django,命名項目名的時候名字不能爲中文
​ 建立app,在Application中添加應用的名,直接建立項目及應用;能夠不添加,後期手動建立應用。

方法二:打開菜單欄Tools>>>run manage task功能欄建立項目及應用

建立好的app須要在django配置文件中註冊方可生效

強調:
1.用Django必定要保證只有一個在運行狀態
2.調試Django項目的時候,必定記得清除瀏覽器的緩存(若是頁面調試沒有達到代碼改的效果)
瀏覽器頁面右鍵:檢查》network》 Settings》Preferences》Network》Disable cache(while DevTools is open) 打上勾;

3.若是想一想使用Django默認的端口能夠本身修改,方法以下圖:

app的概念

django是一個以開發app爲主要功能的web框架
app就是application應用的意思
一個django項目就是一所大學(空的架子 自己沒有任何功能),而app就相似於大學裏面的各個學院;
一個空的django自己沒有任何做用 僅僅是爲app提升前期的環境配置

你能夠根據功能的不一樣 開發多個app
一個app對應一個具體的功能模塊
用戶相關的功能 用戶相關的app
訂單相關的功能 訂單相關的app
商品相關的功能 商品相關的app
每個app都有本身獨立的功能

Django主要文件介紹

應用文件夾(app)
​ migrations 數據庫遷移記錄相關數據
​ adnin.py django後臺管理相關
​ models.py 模型表相關
​ views.py 視圖函數相關

項目名
​ settings.py 配置文件
​ urls.py 路由與視圖函數的映射關係
​ templates文件夾 項目用到的全部的html文件
​ manage.py django入口文件

Django基礎必會的三個函數

​ from django.shortcuts import HttpResponse, render, redirect

HttpResponse
內部傳入一個字符串參數,返回給瀏覽器。

# views.py
def index(request):
    # 業務邏輯代碼
    return HttpResponse("你好,世界!")
# urls.py

from firstapp import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),  # 添加對應的功能函數
]
# 啓動服務端:Starting development server at http://127.0.0.1:9999/
# 在瀏覽器頁面用 http://127.0.0.1:9999/index/鏈接服務端,將index函數內部字符串渲染到瀏覽器頁面上。

render
除request參數外還接受一個待渲染的模板文件和一個保存具體數據的字典參數。
將數據填充進模板文件,最後把結果返回給瀏覽器。(相似於咱們上面用到的jinja2)

# views.py
def reg(request):
     user_dic = {'username':'zhang','password':123}
    #  下面兩種方法均可以
    return render(request,'reg.html',local())  # 拿到reg函數內部全部的局部變量,在html文件內部能夠根據模板語法選擇你要渲染到前端頁面上的變量。
    # return render(request,'reg.html',{'user_dic':user_dic})
# urls.py
from firstapp import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^reg/', views.reg),
]
# templates 文件夾創建 reg.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
<form action="" class="form-control">
    <label for="">username:<input type="text"></label>
    <label for="">password<input type="text"></label>
    <input type="submit" class="提交">
    {{ user_dic }}
    <div>{{user_dic.username }}</div>
    <div>{{ user_dic.password }}</div>  # 只支持點的方式,不支持字典的取值方式
</body>
</form>
</body>
</html>
# 啓動服務端:Starting development server at http://127.0.0.1:9999/# 在瀏覽器頁面用 http://127.0.0.1:9999/reg/鏈接服務端,將reg函數內部reg.html 文件渲染到瀏覽器頁面上。

redirect(重定向)
接受一個URL參數,表示跳轉到指定的URL(當前頁面跳轉)。

​ 1)能夠寫本網站的路徑後綴;

​ 2)也能夠寫全路徑,即:任意一個網頁地址。

# views.py
def login(request):
    # return redirect('http://www.baidu.com') # 訪問login後綴名,重定向到百度網址
    return redirect('/reg') # 本網站的後綴名


# urls.py
from firstapp import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^reg/', views.reg),
    url(r'^login/', views.login),
]
# 啓動服務端:Starting development server at http://127.0.0.1:9999/# 在瀏覽器頁面用 http://127.0.0.1:9999/login/鏈接服務端,按照login函數內部redirect指定的網址跳轉,或者路徑=後綴。

注意:Django能自動識別到你對代碼的修改,因此無需重啓服務端,可是有時候識別比較緩慢,最好從新手動啓動,也能夠多刷新幾回瀏覽器頁面

下一篇:Django 之 文件配置、pycharm及django鏈接數據庫、創表及表的增刪改查02

相關文章
相關標籤/搜索