一. 初識(shí)web框架
為建昌等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及建昌網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站建設(shè)、建昌網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
1. http協(xié)議
http協(xié)議是無(wú)狀態(tài),短連接的??蛻?hù)端連接服務(wù)器,發(fā)送請(qǐng)求,服務(wù)器響應(yīng)請(qǐng)求后斷開(kāi)連接。
2. socket簡(jiǎn)介
所有的網(wǎng)絡(luò)請(qǐng)求都是基于socket,瀏覽器是socket客戶(hù)端,網(wǎng)站是socket服務(wù)端。
3. socket服務(wù)端概述
根據(jù)url的不同返回給用戶(hù)不同的內(nèi)容,使用路由系統(tǒng),路由系統(tǒng)是url與函數(shù)的對(duì)應(yīng)關(guān)系。返回給用戶(hù)的內(nèi)容本質(zhì)是字符串,基本上返回的內(nèi)容是動(dòng)態(tài)的,所以需要使用到模板渲染。模板渲染實(shí)際上是把html充當(dāng)模板,自己創(chuàng)造任意數(shù)據(jù)替換模板中的特殊字符,比如替換特殊字符為數(shù)據(jù)庫(kù)中的數(shù)據(jù)。
4. 自己寫(xiě)web框架
靜態(tài)應(yīng)用
# coding:utf-8
import socket
def f1(request):
'''
處理用戶(hù)請(qǐng)求,并返回相應(yīng)的內(nèi)容
:param request:用戶(hù)請(qǐng)求的所有信息
:return:返回相應(yīng)的內(nèi)容
'''
return b'f1'
def f2(request):
'''
處理用戶(hù)請(qǐng)求,并返回相應(yīng)的內(nèi)容
:param request:
:return:
'''
f = open('index.html', 'rb')
data = f.read()
f.close()
return data
def f3(request):
'''
處理用戶(hù)請(qǐng)求,并返回相應(yīng)的內(nèi)容
:param request:
:return:
'''
f = open('news.html', 'rb')
data = f.read()
f.close()
return data
routers = [
('/user', f1),
('/', f2)
]
def run():
sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)
while True:
conn, addr = sock.accept()
'''
有用戶(hù)來(lái)連接,
獲取用戶(hù)發(fā)送的數(shù)據(jù)
'''
data = conn.recv(8096)
print(data)
'''請(qǐng)求頭:
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1\
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Purpose: prefetch
Accept-Encoding: gzip, deflate,
Accept-Language: zh-CN,zh;q=0.9
'''
# 解析請(qǐng)求頭,目標(biāo):獲取請(qǐng)求頭中的url,并根據(jù)url向服務(wù)端發(fā)送請(qǐng)求
data = str(data, encoding='utf-8')
headers, bodys = data.split('\r\n\r\n')
headers_list = headers.split('\r\n')
methods, url, protocal = headers_list[0].split(' ')
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 = '404'
# if url == '/user':
# conn.send(b'user page')
# else:
# conn.send(b'404 is not found!')
# conn.send(b"HTTP/1.1 200 OK\r\n\r\n") # 響應(yīng)頭
# conn.send(b"hello thanlon!") # 相應(yīng)體
conn.close()
if __name__ == '__main__':
run()
動(dòng)態(tài)應(yīng)用示例一
# coding:utf-8
import socket
def f1(request):
'''
處理用戶(hù)請(qǐng)求,并動(dòng)態(tài)返回相應(yīng)的內(nèi)容
:param request:
:return:
'''
f = open('news.html', 'r', encoding='utf-8')
data = f.read()
f.close()
import time
ctime = time.time()
data = data.replace('%', str(ctime))
return bytes(data, encoding='utf-8')
routers = [
('/user', f1),
]
def run():
sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)
while True:
conn, addr = sock.accept()
'''
有用戶(hù)來(lái)連接,
獲取用戶(hù)發(fā)送的數(shù)據(jù)
'''
data = conn.recv(8096)
print(data)
'''請(qǐng)求頭:
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1\
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Purpose: prefetch
Accept-Encoding: gzip, deflate,
Accept-Language: zh-CN,zh;q=0.9
'''
# 解析請(qǐng)求頭,目標(biāo):獲取請(qǐng)求頭中的url,并根據(jù)url向服務(wù)端發(fā)送請(qǐng)求
data = str(data, encoding='utf-8')
headers, bodys = data.split('\r\n\r\n')
headers_list = headers.split('\r\n')
methods, url, protocal = headers_list[0].split(' ')
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 = '404'
# if url == '/user':
# conn.send(b'user page')
# else:
# conn.send(b'404 is not found!')
# conn.send(b"HTTP/1.1 200 OK\r\n\r\n") # 響應(yīng)頭
# conn.send(b"hello thanlon!") # 相應(yīng)體
conn.close()
if __name__ == '__main__':
run()
動(dòng)態(tài)應(yīng)用示例二
# coding:utf-8
import socket
def f1(request):
import pyMySQL
# 創(chuàng)建連接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')
# 創(chuàng)建游標(biāo)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執(zhí)行sql語(yǔ)句,并返回受影響的行數(shù)
cursor.execute("select id,name,passwd from userinfo")
user_list = cursor.fetchall()
cursor.close()
conn.close()
# print(user_list)
content_list = []
for row in user_list:
tp = '%s%s%s' % (row['id'], row['name'], row['passwd'],)
content_list.append(tp)
content = ''.join(content_list)
f = open('userlist.html', 'r', encoding='utf-8')
template = f.read()
f.close()
data = template.replace('{{content}}', content)
print(data)
return bytes(data, encoding='utf-8')
routers = [
('/user', f1),
]
def run():
sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(5)
while True:
conn, addr = sock.accept()
'''
有用戶(hù)來(lái)連接,
獲取用戶(hù)發(fā)送的數(shù)據(jù)
'''
data = conn.recv(8096)
# print(data)
'''請(qǐng)求頭:
GET / HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1\
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Purpose: prefetch
Accept-Encoding: gzip, deflate,
Accept-Language: zh-CN,zh;q=0.9
'''
# 解析請(qǐng)求頭,目標(biāo):獲取請(qǐng)求頭中的url,并根據(jù)url向服務(wù)端發(fā)送請(qǐng)求
data = str(data, encoding='utf-8')
headers, bodys = data.split('\r\n\r\n')
headers_list = headers.split('\r\n')
methods, url, protocal = headers_list[0].split(' ')
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()
5. web框架的分類(lèi)
為了方便開(kāi)發(fā)者開(kāi)發(fā)web應(yīng)用,web框架應(yīng)用而生。有的web框架幫助開(kāi)發(fā)者構(gòu)建好了socket服務(wù)端,有的web框架幫助開(kāi)發(fā)者寫(xiě)好了模板渲染??傊柚鷚eb框架可以減輕了開(kāi)發(fā)者的工作量。flask框架只有路由系統(tǒng),沒(méi)有socket服務(wù)端和模板引擎,socket服務(wù)端使用是python第三方模塊,如wsgiref。模板引擎使用的也是第三方模塊jinjia2。django框架有路由系統(tǒng)、模板引擎,但是沒(méi)有socket服務(wù)端,socket服務(wù)端使用的是python的第三方內(nèi)置模塊wsgiref,wsgiref把請(qǐng)求交給django做處理。另外,還有一種叫Tornado的框架,Tornado框架包含socket服務(wù)端、路由系統(tǒng)、模板引擎??梢詫eb框架這樣分類(lèi),django框架和其它框架。因?yàn)閐jango框架提供了很多特殊的功能,如緩存、分布式。其它框架是輕量級(jí)的web框架。
二. 初識(shí)django
安裝django:pip3 install django
創(chuàng)建django程序:django-admin startproject 項(xiàng)目名稱(chēng)
運(yùn)行django程序:python manager.py runserver 127.0.0.1:8080(如果不指定,默認(rèn)運(yùn)行在8000端口)
三. django程序目錄
manager.py:對(duì)當(dāng)前django程序所有操作可以基于python manager.py runserver
settings.py:django配置文件
url.py:路由系統(tǒng),url->函數(shù)
wsgi.py:用于定義django使用什么socket服務(wù)端,如wsgiref,uwsgi(wsgiref性能比較低)
四. 第一個(gè)django請(qǐng)求
usr.py:
from django.shortcuts import HttpResponse
# 處理請(qǐng)求的函數(shù)
def login(request): #
'''
處理用戶(hù)請(qǐng)求,返回相響應(yīng)結(jié)果
:param request:用戶(hù)請(qǐng)求的相關(guān)信息(不是字節(jié),是對(duì)象)
:return:
'''
pass
return HttpResponse('login!')
# url
urlpatterns = [
# path('admin/', admin.site.urls),
path('login/', login),
]
四. 靜態(tài)文件以及模板的配置
1. 靜態(tài)文件路徑的配置
創(chuàng)建靜態(tài)文件目錄也需要配置:
修改settings.py:
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
'''
只要是使用/static/的前綴,就在這個(gè)目錄(static目錄)下找靜態(tài)文件
'''
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
2. HttpResponse與render函數(shù)
返回字符串
return HttpResponse(‘login!’)
return HttpResponse(’< input type=“text”>’)
返回模板
render函數(shù)默認(rèn)是在“templates”中自動(dòng)找文件,讀取文件內(nèi)容后返回給用戶(hù)。
return render(request, ‘xxx.html’)
render函數(shù)本質(zhì)上是調(diào)用HttpResponse。
3. 模板路徑的配置
模板名稱(chēng)需要與配置文件設(shè)定的模板名字一致,
五. 創(chuàng)建程序步驟
1. 創(chuàng)建project
django-admin startproject project名,也可以在pycharm中選擇Django,創(chuàng)建project
2. 配置模板路徑
創(chuàng)建templates目錄,然后修改配置文件:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]#BASE_DIR指當(dāng)前路徑
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
3. 配置靜態(tài)文件目錄
創(chuàng)建static目錄,然后修改配置文件:
'''
只要是使用/static/的前綴,就在這個(gè)目錄下找靜態(tài)文件
'''
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
4. 額外配置
將 django.middleware.csrf.CsrfViewMiddleware注釋掉:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
六. 用戶(hù)登錄示例
urls.py:
from django.contrib import admin
from django.urls import path
from django.shortcuts import HttpResponse, render, redirect
def login(request): #
'''
處理用戶(hù)請(qǐng)求,返回相響應(yīng)結(jié)果
:param request:用戶(hù)請(qǐng)求的相關(guān)信息(不是字節(jié),是對(duì)象)
:return:
'''
if request.method == 'GET':
return render(request, 'login.html') # 本質(zhì)上是調(diào)用HttpResponse,自動(dòng)找到login.html文件,讀取內(nèi)容并返回給用戶(hù)
else:
# print(request.POST) # 用戶(hù)POST提交的數(shù)據(jù)(請(qǐng)求體)
# user = request.POST['username']#直接索引,如果沒(méi)有username會(huì)報(bào)錯(cuò)
username = request.POST.get('username') # 如果沒(méi)有username不會(huì)報(bào)錯(cuò),返回None
pwd = request.POST.get('pwd') # 如果沒(méi)有username不會(huì)報(bào)錯(cuò),返回None
if username == 'thanlon' and pwd == '123456':
return redirect('https://www.blueflags.cn')
else:
return render(request, 'login.html', {'msg': '用戶(hù)名或密碼錯(cuò)誤!'}) # django內(nèi)部做模板渲染
urlpatterns = [
# path('admin/', admin.site.urls),
path('login/', login),
]
login.html:
用戶(hù)名
密碼
{{ msg }}
登錄
登錄效果:
七. request.GET與 request.POST
1. request.GET
request.GET是從請(qǐng)求頭的url中獲取值
2. request.POST
request.POST是從請(qǐng)求體中獲取值。GET請(qǐng)求時(shí),只有request.GET可以獲取值。但POST請(qǐng)求時(shí),request.POST和request.GET都可能獲取值。
……
可以通過(guò)request.GET獲取url中的page
八. django模板語(yǔ)言特殊標(biāo)記(重點(diǎn)內(nèi)容)
1. 取字符串的值
def index(request):
return render(request, 'index/index.html', {'username': '一問(wèn)奈何'})
{{ username }}
# 一問(wèn)奈何
2. 取列表的值
def index(request):
# return render(request, 'index/index.html', {'username': '一問(wèn)奈何'})
return render(request, 'index/index.html', {'username': ['thanlon','Kiku']})
直接通過(guò)索引
{#
{{ username }}
#}
{{ username }}
{{ username.0 }}
{{ username.1 }}
通過(guò)循環(huán)遍歷
{% for item in username %}
{{ item }}
{% endfor %}
3. 取字典的值
def index(request):
return render(request, 'index/index.html', {
'user_dict': {'name': '一問(wèn)奈何', 'age': 23}
})
{{ user_dict.name }}
{{ user_dict.age }}
4. 取嵌套于列表中字典的值
def index(request):
return render(request, 'index/index.html', {
'user_list_dict': [
{'id': 1, 'name': 'thanlon'},
{'id': 2, 'name': 'kuku'},
]
})
通過(guò)索引取值
{{ user_list_dict.0.id}}--{{ user_list_dict.0.name}}
{{ user_list_dict.1.id}}--{{ user_list_dict.0.name}}
通過(guò)循環(huán)取值
{% for row in user_list_dict %}
{{ row.id }}--{{ row.name }}
{% endfor %}
九. 學(xué)生信息管理系統(tǒng)-數(shù)據(jù)庫(kù)表的結(jié)構(gòu)設(shè)計(jì)
mysql> create table class
-> (
-> id int auto_increment primary key,
-> title varchar(20) not null
-> );
mysql> create table student
-> (
-> id int auto_increment primary key,
-> name varchar(10) not null,
-> class_id int not null
-> );
mysql> create table teacher
-> (
-> id int auto_increment primary key,
-> name varchar(10) not null
-> );
mysql> create table teacher2class
-> (
-> id int primary key,
-> teacher_id int not null,
-> class_id int not null
-> );
十. 學(xué)生信息管理系統(tǒng)-查詢(xún)班級(jí)信息列表與添加班級(jí)信息
1. 向班級(jí)表中添加數(shù)據(jù)
mysql> insert class values(null,'軟件工程'),(null,'計(jì)算機(jī)科學(xué)與技術(shù)');
2. 查詢(xún)班級(jí)信息
新建文件夾app01,并在文件夾中新建views.py
配置路徑,修改urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('classes/', views.classes),
]
在views.py的classes函數(shù)(路徑對(duì)應(yīng)此函數(shù))中寫(xiě)查詢(xún)班級(jí)信息的邏輯代碼
from django.shortcuts import render, redirect
import pymysql
def classes(request):
'''
查詢(xún)班級(jí)id、班級(jí)名稱(chēng)
:param request:對(duì)象相關(guān)的數(shù)據(jù)
:return:渲染后的模板
'''
# 創(chuàng)建連接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')
# 創(chuàng)建游標(biāo)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 執(zhí)行sql語(yǔ)句
cursor.execute("select id,title from class")
classes_list = cursor.fetchall()
cursor.close()
conn.close()
return render(request, 'classes.html', {'classes_list': classes_list})
在templates文件夾下新建classes.html
添加無(wú)錫×××醫(yī)院 http://www.bhnkyixue.com/
{% for row in classes_list %}
{{ row.id }}
{{ row.title }}
{% endfor %}
運(yùn)行程序后,訪問(wèn)http://127.0.0.1:8000/classes/可以查看到頁(yè)面效果:
3. 添加班級(jí)信息
配置路徑,修改urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('classes/', views.classes),
path('add-class/', views.add_class),
]
在templates文件夾下新建add_class.html
添加班級(jí)
班級(jí)名稱(chēng):
在views.py的add_class函數(shù)中寫(xiě)添加學(xué)生班級(jí)信息的邏輯代碼
def add_class(request):
if request.method == 'GET':
return render(request, 'add_class.html')
else:
class_title = request.POST.get('class_title')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# cursor.execute("insert into class(title) values(%s)", [class_title, ])
cursor.execute('insert into class(title) values(%s)', class_title)
conn.commit()
cursor.close()
conn.close()
return redirect('/classes/')
程序正常運(yùn)行后,在班級(jí)信息頁(yè)面(http://127.0.0.1:8000/classes/)中點(diǎn)擊添加按鈕,進(jìn)入添加班級(jí)信息界面(http://127.0.0.1:8000/add-class/)。提交添加的班級(jí)信息后,自動(dòng)跳轉(zhuǎn)到班級(jí)信息頁(yè)面。
十. 學(xué)生信息管理系統(tǒng)-刪除班級(jí)信息
view.py
def del_class(request):
nid = request.GET.get('nid')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# cursor.execute("insert into class(title) values(%s)", [class_title, ])
cursor.execute('delete from class where id=%s', nid)
conn.commit()
cursor.close()
conn.close()
return redirect('/classes/')
瀏覽器向服務(wù)端發(fā)送刪除數(shù)據(jù)的請(qǐng)求,服務(wù)端接收請(qǐng)求刪除數(shù)據(jù)后向?yàn)g覽器發(fā)送響應(yīng),告訴瀏覽器重定向到/classes/。服務(wù)端向?yàn)g覽器發(fā)送響應(yīng)的響應(yīng)頭中有l(wèi)ocation:http://127.0.0.1:8000/classes/,即是:告訴瀏覽器向此鏈接發(fā)送一次請(qǐng)求。
十一. 學(xué)生信息管理系統(tǒng)-編輯班級(jí)信息
view.py:
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='wwwnxl', db='test')
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()
return render(request, 'edit_class.html', {'result': result})
else:
# nid = request.POST.get('nid') # 放到請(qǐng)求體
nid = request.GET.get('nid') # 放到請(qǐng)求頭
title = request.POST.get('title')
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')
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/')
edit_class.html:
編輯班級(jí)信息
班級(jí)名稱(chēng):
{# #}
網(wǎng)頁(yè)名稱(chēng):Django框架從入門(mén)到應(yīng)用
分享路徑:http://aaarwkj.com/article34/iijppe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、網(wǎng)站策劃、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈、虛擬主機(jī)、網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)