1. 程式人生 > >Django框架基礎知識彙總(有專案版)

Django框架基礎知識彙總(有專案版)

Web框架本質

web系統概念

1. Http,無狀態,短連線
2. 瀏覽器(socket客戶端)、網站(socket服務端)

web框架本質

import socket  
def handle_request(client):
    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n")
    client.send("Hello, Seven")  
def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost'
,8000)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()

自定義Web框架

a. socket服務端
b. 根據URL不同返回不同的內容
路由系統:
URL -> 函式
c. 字串返回給使用者
模板引擎渲染:
HTML充當模板(特殊字元)
自己創造任意資料
字串
  • 靜態網站處理方式:
import socket

def f1(request):
    """
    處理使用者請求,並返回相應的內容
    :param request: 使用者請求的所有資訊
    :return:
    """
    f = open('index.fsw','rb')
    data = f.read()
    f.close()
    return data

def f2(request):
    f = open('aricle.tpl','rb')
    data = f.read()
    f.close()
    return
data routers = [ ('/xxx', f1), ('/ooo', f2), ] def run(): sock = socket.socket() sock.bind(('127.0.0.1',8080)) sock.listen(5) while True: conn,addr = sock.accept() # hang住 # 有人來連線了 # 獲取使用者傳送的資料 data = conn.recv(8096) data = str(data,encoding='utf-8') headers,bodys = data.split('\r\n\r\n') temp_list = headers.split('\r\n') method,url,protocal = temp_list[0].split(' ') conn.send(b"HTTP/1.1 200 OK\r\n\r\n") func_name = None for item in routers: if item[0] == url: func_name = item[1] break if func_name: response = func_name(data) else: response = b"404" conn.send(response) conn.close() if __name__ == '__main__': run()
  • 動態網站處理方式一(手動進行替換的模版引擎):
import socket
def f3(request):
    import pymysql
    # 建立連線,獲得資料
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123',db='db666')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute('select id,username,password from userinfo')
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    # 組裝資料模型
    content_list=[]
    for row in user_list:
        tp = '<tr><td>%s</td><td>%s</td><td>%s</td></tr>'%(row['id'],row['username'],row['password'])
        content_list.append(tp)
    content = "".join(content_list) # 將列表中的資料拼接成字串

    # 模板渲染(模板+資料)
    f = open('userlist.html','r',encoding='utf-8')
    template = f.read()
    f.close()
    data = template.replace('@@[email protected]@', content)
    return bytes(data, encoding='utf-8')

# 路由系統
routers = [
    ('/userlist.htm', f3),    
]

def run():
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('127.0.0.1',8080))
    sock.listen(5)

    while True:
        conn,addr = sock.accept() # hang住
        # 有人來連線了
        # 獲取使用者傳送的資料
        data = conn.recv(8096)
        data = str(data,encoding='utf-8')
        headers,bodys = data.split('\r\n\r\n')
        temp_list = headers.split('\r\n')
        method,url,protocal = temp_list[0].split(' ')
        conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response = func_name(data)
        else:
            response = b"404"

        conn.send(response)
        conn.close()

if __name__ == '__main__':
    run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>使用者名稱</th>
                <th>郵箱</th>
            </tr>
        </thead>

        <tbody>
            @@[email protected]@
        </tbody>
    </table>
</body>
</html>

動態網站二(使用jinjia2模板引擎進行替換)

import socket
def f4(request):
    import pymysql
    # 建立連線
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='db666')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select id,username,password from userinfo")
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()

    f = open('hostlist.html','r',encoding='utf-8')
    data = f.read()
    f.close()

    # 基於第三方工具實現的模板渲染
    from jinja2 import Template
    template = Template(data)
    data = template.render(xxxxx=user_list, user='dsafsdfsdf')
    return data.encode('utf-8')

# 路由系統
routers = [
      ('/host.html', f4),
]

def run():
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('127.0.0.1',8080))
    sock.listen(5)

    while True:
        conn,addr = sock.accept() # hang住
        # 有人來連線了
        # 獲取使用者傳送的資料
        data = conn.recv(8096)
        data = str(data,encoding='utf-8')
        headers,bodys = data.split('\r\n\r\n')
        temp_list = headers.split('\r\n')
        method,url,protocal = temp_list[0].split(' ')
        conn.send(b"HTTP/1.1 200 OK\r\n\r\n")

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response = func_name(data)
        else:
            response = b"404"

        conn.send(response)
        conn.close()

if __name__ == '__main__':
    run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>使用者名稱</th>
                <th>郵箱</th>
            </tr>
        </thead>
        <tbody>
            {% for row in xxxxx %}
                <tr>
                    <td>{{row.id}}</td>
                    <td>{{row.username}}</td>
                    <td>{{row.password}}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    {{user}}
</body>
</html>

Django框架基礎內容

框架種類

- a,b,c --> Tornado
- [第三方a],b,c          --> wsgiref -> Django 
- [第三方a],b,[第三方c]  --> flask,

Django專案前期配置

pip3 install django
# 建立Django程式
django-admin startproject mysite
# 進入程式目錄
cd mysite
# 啟動socket服務端,等待使用者傳送請求
python manage.py runserver 127.0.0.1:8080
 Django配置檔案:settings.py 
……
DIRS': [os.path.join(BASE_DIR, 'template')],
……
Mysql資料庫:
DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

#備註:
# 由於Django內部連線MySQL時使用的是MySQLdb模組,而python3中還無此模組,所以需要使用pymysql來代替  
# 如下設定放置的與project同名的配置的 __init__.py檔案中  
import pymysql
pymysql.install_as_MySQLdb() 
靜態檔案路徑:
static目錄
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
額外配置(跨站請求偽裝crsf):
MIDDLEWARE = [
……
#'django.middleware.csrf.CsrfViewMiddleware',
……
]

專案案例

  • 網站請求
# urls.py

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
     url(r'^index/',index),
]
def index(request):
    # return HttpResponse('Index')
    return render(request, 'index.html',{
        'name': 'tom',
        'users':['李志','李傑'],
        'user_dict':{'k1':'v1', 'k2':'v2'},
        'user_list_dict':[
            {'id':1,'name':'tom','email':'[email protected]'},
            {'id':1,'name':'tom','email':'[email protected]'},
            {'id':1,'name':'tom','email':'[email protected]'},
            {'id':1,'name':'tom','email':'[email protected]'},
        ]
    })
# template/index

<p>{{ name }}</p>
<p>{{ users.0 }}</p>
<p>{{ users.1 }}</p>
<p>{{ user_dict.k1 }}</p>
<p>{{ user_dict.k2 }}</p>
<h3>迴圈</h3>
<ul>
    {% for item in users %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>
<h3>迴圈</h3>
<table border="1">
    {% for row in user_list_dict %}
        <tr>
            <td>{{ row.id }}</td>
            <td>{{ row.name }}</td>
            <td>{{ row.email }}</td>
            <td>
                <a>編輯</a> | <a href="/del/?nid={{ row.id }}">刪除</a>
            </td>
        </tr>
    {% endfor %}
</table>
  • 網站登陸
# urls

from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import HttpResponse,render,redirect

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^login/',login),
]
def login(request):
    """
    處理使用者請求,並返回內容
    :param request: 使用者請求相關的所有資訊(物件)
    :return:
    """
    # 字串
    # return HttpResponse('<input type="text" />')
    # return HttpResponse('login.html')
    # 自動找到模板路徑下的login.html檔案,讀取內容並返回給使用者
    # 模板路徑的配置

    print(request.GET)  # 結果為字典格式,值為列表型別
    if request.method == "GET":
        return render(request,'login.html')
    else:
        # 使用者POST提交的資料(請求體)
        u = request.POST.get('user')
        p = request.POST.get('pwd')
        if u == 'root' and p == '123':
            # 登入成功
            # return redirect('http://www.oldboyedu.com')
            return redirect('/index/')   # 重定向
        else:
            # 登入失敗
            return render(request,'login.html',{'msg': '使用者名稱或密碼錯誤'})
# template

<form method="POST" action="/login/">
    <input type="text" name="user" />
    <input type="password" name="pwd" />
    <input type="submit" value="登入" />
    {{ msg }}
</form>

django學員管理系統

資料庫設計結構

表結構:班級\學生\老師
(班級表):
id    title
1425期 

(學生表):
id     name      班級ID(FK)
 1     張傑      1

(老師表):
id        name
1       林峰
2       林狗
3       苑天

(老師班級關係表):
id     老師ID    班級ID
1       1          1
2       1          2
3       2          2

班級管理模組

  • 查(母版繼承)
# urls

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'classes/', views.classes),
   ]
# view

from django.shortcuts import render,redirect
import pymysql

def classes(request):
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='123', db='s4db65', charset='utf8')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 設定查詢結果為字典格式
    cursor.execute("select id, title from class")
    class_list = cursor.fetchall()  # 結果為字典
    cursor.close()
    conn.close()
    print(class_list)
    return render(request, 'classes.html',{'class_list':class_list})
# html

{% extends ‘manage.html’% } # 繼承母版
{%block content%} # 母版塊中填充內容

<h1>班級列表</h1>
<div>
    <a href="/add_class/">新增</a>
</div>
<table>
    <thead>
    <tr>
        <th>ID</th>
        <th>班級名稱</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    {% for row in class_list %}
        <tr>
            <td>{{ row.id }}</td>
            <td>{{ row.title }}</td>
            <td>
                <a href="">編輯</a>
                |
                <a href="">刪除</a>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>
{% endbloc %}
# urls

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^add_class/', views.add_class),
]
# view

def add_class(request):
    if request.method == 'GET':
        return render(request,'add_class.html')
    else:
        print(request.POST)
        v = request.POST.get('title')
        conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='s4db65',charset='utf8')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute('insert into class(title) value(%s)', [v,])
        conn.commit()   # 提交事務
        cursor.close()
        conn.close()
        return redirect('/classes/')
# html

<h1>新增班級</h1>
<form method="post" action="/add_class/">
    <p>班級名稱:<input type="text" name="title" /></p>
    <input type="submit" value="提交">
</form>
# urls

urlpatterns = [
      url(r'^del_class/', views.del_class),
  ]
# view

def del_class(request):
   nid = request.GET.get('nid')
   conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='s4db65', charset='utf8')
   cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
   cursor.execute('delete from class where id=%s',[nid,])
   conn.commit()
   cursor.close()
   conn.close()
   return redirect('/classes/')
# urls

urlpatterns = [
    url(r'^edit_class/', views.edit_class),
]
# view

def edit_class(request):
    if request.method == 'GET': # 獲取資料
        nid = request.GET.get('nid')
        conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd = '123', db='s4db65',charset='utf8')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute('select id, title from class where id=%s', [nid,])
        result = cursor.fetchone()
        cursor.close()
        conn.close()
        print(result)
        return render(request,'edit_class.html',{'result':result})
    else:
        nid = request.GET.get('nid')
        title = request.POST.get('title')
        print(nid, title)
        conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='s4db65', charset='utf8')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute('update class set title=%s where id=%s',[title,nid,])
        conn.commit()
        cursor.close()
        conn.close()
        return redirect('/classes/')
  • 模態對話方塊實現增加班級功能
# html

<a onclick="showModal()">對話方塊新增</a>
<div id="shadow" class="shadow hide"></div>
<div id="modal" class="model hide">
    <p>
        <input type="text" id="title">
    </p>
    <input type="button" value="提交" onclick="AjaxSend()"/><span id=""></span>
    <input type="button" value="取消" onclick="cancleModal()">
</div>
# css

.hide {
    display: none;
}
.shadow {
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.5;
    z-index: 999;
}
.model {
    z-index: 1000;
    position: fixed;
    height: 300px;
    width: 400px;
    background: white;
    left: 50%;
    top: 50%;
    margin-left: -200px;
    margin-top: -150px;
}
# js

function showModal() {
    document.getElementById('shadow').classList.remove('hide')
    document.getElementById('modal').classList.remove('hide')
}
function cancleModal() {
    document.getElementById('shadow').classList.add('hide');
    document.getElementById('modal').classList.add('hide');
}
function AjaxSend() {
    $.ajax({
        url: '/modal_add_class/',
        type: 'POST',
        data: {'title': $('#title').val()},
        success: function (data) {
            console.log(data);
            if (data == 'ok') {
                location.href = '/classes';
            } else {
                $('errormsg').text(data);
            }
        }
    })
}
# urls

urlpatterns = [url(r'^modal_add_class/', views.modal_add_class]
# views

sqlheper工具類(將增刪改查進行封裝):
def modify(sql,args):
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='s4db65', charset='utf8')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute(sql,args)
    conn.commit()
    cursor.close()
    conn.close()


----------


def modal_add_class(request):
    title = request.POST.get('title')
    if len(title) > 0:
        sqlheper.modify('insert into class (title) value(%s)',[title,])
        return HttpResponse('ok')
    else:
        return HttpResponse('班級標題不能為空')

學生管理模組

# urls

url(r'^students/',views.students),
# views

def students(request):
    conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='s4db65',charset='utf8')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute('select student.id,student.name,class.title from student left JOIN class on student.class_id = class.id')
    student_list = cursor.fetchall()
    cursor.close()
    conn.close()
    print('結果:',student_list)
    return render(request,'students.html',{'student_list':student_list})
# html

<h1>學生列表</h1>
<div><a href="/add_student/">新增</a></div>
<table>
    <thead>
    <tr>
        <th>ID</th>
        <th>學生姓名</th>
        <th>所屬班級</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    {% for row in student_list %}
        <tr>
            <td>{{ row.id }}</td>
            <td>{{ row.name }}</td>
            <td>{{ row.title }}</td>
            <td>
                <a href=" ">編輯</a>
                <a>刪除</a>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>
# urls

url(r'^add_student/',views.add_student)
# views

def add_student(request):
    if request.method == 'GET':  #只負責跳轉頁面
        conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='s4db65',charset='utf8')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute('select id,title from class')
        class_list = cursor.fetchall()
        cursor.close()
        conn.close()
        return render(request,'add_student.html',{'class_list':class_list})
    else:
        name = request.POST.get('name')  #負責提交資料的跳轉頁面
        class_id = request.POST.get('class_id')
        conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123',db='s4db65',charset='utf8')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        cursor.execute('insert into student(name,class_id)values(%s,%s)',[name,class_id,])
        conn.commit()
        cursor.close()
        conn.close()
        return redirect('/students/')
# html

<h1>新增學生</h1>
<form method="post" action="/add_student/">
    <p>學生姓名<input type="text" name="name"> </p>
    <p>
        所屬班級
        <select name='class_id'>
            {% for row in class_list %}
            <option value="{{ row.id }}">{{ row.title }}</option>
            {% endfor %}
        </select>
    </p>
<input type="submit" value="提交" />
</form>
# urls

url(r'^edit_student/',views.edit_student),
# views

from utils import sqlheper
def edit_student(request):
    if request.method == "GET":
        nid = request.GET.get('nid')
        class_list = sqlheper.get_list("select id,title from class",[])
        current_student_info = sqlheper.get_one('select id,name,class_id from student where id=%s',[nid,])
        print('結果:',class_list,current_student_info,nid)
        return render(request,'edit_student.html',{'class_list': class_list,'current_student_info':current_student_info})
    else:
        nid = request.GET.get('nid')
        name = request.POST.get('name')
        class_id = request.POST.get('class_id')
        sqlheper.modify('update student set name=%s,class_id=%s where id=%s',[name,class_id,nid,])
        return redirect('/students/')