Django框架从入门到应用

一. 初识web框架

为建昌等地区用户提供了全套网页设计制作服务,及建昌网站建设行业解决方案。主营业务为成都做网站、网站建设、建昌网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

1. http协议

http协议是无状态,短连接的。客户端连接服务器,发送请求,服务器响应请求后断开连接。

2. socket简介

所有的网络请求都是基于socket,浏览器是socket客户端,网站是socket服务端。

3. socket服务端概述

根据url的不同返回给用户不同的内容,使用路由系统,路由系统是url与函数的对应关系。返回给用户的内容本质是字符串,基本上返回的内容是动态的,所以需要使用到模板渲染。模板渲染实际上是把html充当模板,自己创造任意数据替换模板中的特殊字符,比如替换特殊字符为数据库中的数据。

4. 自己写web框架

静态应用

# coding:utf-8

import socket

def f1(request):

'''

处理用户请求,并返回相应的内容

:param request:用户请求的所有信息

:return:返回相应的内容

'''

return b'f1'

def f2(request):

'''

处理用户请求,并返回相应的内容

:param request:

:return:

'''

f = open('index.html', 'rb')

data = f.read()

f.close()

return data

def f3(request):

'''

处理用户请求,并返回相应的内容

: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()

'''

有用户来连接,

获取用户发送的数据

'''

data = conn.recv(8096)

print(data)

'''请求头:

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

'''

# 解析请求头,目标:获取请求头中的url,并根据url向服务端发送请求

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") # 响应头

# conn.send(b"hello thanlon!") # 相应体

conn.close()

if __name__ == '__main__':

run()

动态应用示例一

# coding:utf-8

import socket

def f1(request):

'''

处理用户请求,并动态返回相应的内容

: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()

'''

有用户来连接,

获取用户发送的数据

'''

data = conn.recv(8096)

print(data)

'''请求头:

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

'''

# 解析请求头,目标:获取请求头中的url,并根据url向服务端发送请求

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") # 响应头

# conn.send(b"hello thanlon!") # 相应体

conn.close()

if __name__ == '__main__':

run()

动态应用示例二

# coding:utf-8

import socket

def f1(request):

import pyMySQL

# 创建连接

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')

# 创建游标

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 执行sql语句,并返回受影响的行数

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()

'''

有用户来连接,

获取用户发送的数据

'''

data = conn.recv(8096)

# print(data)

'''请求头:

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

'''

# 解析请求头,目标:获取请求头中的url,并根据url向服务端发送请求

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框架的分类

为了方便开发者开发web应用,web框架应用而生。有的web框架帮助开发者构建好了socket服务端,有的web框架帮助开发者写好了模板渲染。总之,借助web框架可以减轻了开发者的工作量。flask框架只有路由系统,没有socket服务端和模板引擎,socket服务端使用是python第三方模块,如wsgiref。模板引擎使用的也是第三方模块jinjia2。django框架有路由系统、模板引擎,但是没有socket服务端,socket服务端使用的是python的第三方内置模块wsgiref,wsgiref把请求交给django做处理。另外,还有一种叫Tornado的框架,Tornado框架包含socket服务端、路由系统、模板引擎。可以将web框架这样分类,django框架和其它框架。因为django框架提供了很多特殊的功能,如缓存、分布式。其它框架是轻量级的web框架。

二. 初识django

安装django:pip3 install django

创建django程序:django-admin startproject 项目名称

运行django程序:python manager.py runserver 127.0.0.1:8080(如果不指定,默认运行在8000端口)

三. django程序目录

manager.py:对当前django程序所有操作可以基于python manager.py runserver

settings.py:django配置文件

url.py:路由系统,url->函数

wsgi.py:用于定义django使用什么socket服务端,如wsgiref,uwsgi(wsgiref性能比较低)

四. 第一个django请求

usr.py:

from django.shortcuts import HttpResponse

# 处理请求的函数

def login(request): #

'''

处理用户请求,返回相响应结果

:param request:用户请求的相关信息(不是字节,是对象)

:return:

'''

pass

return HttpResponse('login!')

# url

urlpatterns = [

# path('admin/', admin.site.urls),

path('login/', login),

]

四. 静态文件以及模板的配置

1. 静态文件路径的配置

创建静态文件目录也需要配置:

Django框架从入门到应用

修改settings.py:

# Static files (CSS, JavaScript, Images)

# https://docs.djangoproject.com/en/2.2/howto/static-files/

'''

只要是使用/static/的前缀,就在这个目录(static目录)下找静态文件

'''

STATIC_URL = '/static/'

STATICFILES_DIRS = (

os.path.join(BASE_DIR, 'static'),

)

2. HttpResponse与render函数

返回字符串

return HttpResponse(‘login!’)

return HttpResponse(’< input type=“text”>’)

返回模板

render函数默认是在“templates”中自动找文件,读取文件内容后返回给用户。

return render(request, ‘xxx.html’)

render函数本质上是调用HttpResponse。

3. 模板路径的配置

模板名称需要与配置文件设定的模板名字一致,

Django框架从入门到应用

五. 创建程序步骤

1. 创建project

django-admin startproject project名,也可以在pycharm中选择Django,创建project

2. 配置模板路径

创建templates目录,然后修改配置文件:

TEMPLATES = [

{

'BACKEND': 'django.template.backends.django.DjangoTemplates',

'DIRS': [os.path.join(BASE_DIR, 'templates')]#BASE_DIR指当前路径

,

'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. 配置静态文件目录

创建static目录,然后修改配置文件:

'''

只要是使用/static/的前缀,就在这个目录下找静态文件

'''

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',

]

六. 用户登录示例

urls.py:

from django.contrib import admin

from django.urls import path

from django.shortcuts import HttpResponse, render, redirect

def login(request): #

'''

处理用户请求,返回相响应结果

:param request:用户请求的相关信息(不是字节,是对象)

:return:

'''

if request.method == 'GET':

return render(request, 'login.html') # 本质上是调用HttpResponse,自动找到login.html文件,读取内容并返回给用户

else:

# print(request.POST) # 用户POST提交的数据(请求体)

# user = request.POST['username']#直接索引,如果没有username会报错

username = request.POST.get('username') # 如果没有username不会报错,返回None

pwd = request.POST.get('pwd') # 如果没有username不会报错,返回None

if username == 'thanlon' and pwd == '123456':

return redirect('https://www.blueflags.cn')

else:

return render(request, 'login.html', {'msg': '用户名或密码错误!'}) # django内部做模板渲染

urlpatterns = [

# path('admin/', admin.site.urls),

path('login/', login),

]

login.html:

用户名

密码

{{ msg }}

登录

登录效果:

七. request.GET与 request.POST

1. request.GET

request.GET是从请求头的url中获取值

2. request.POST

request.POST是从请求体中获取值。GET请求时,只有request.GET可以获取值。但POST请求时,request.POST和request.GET都可能获取值。

……

可以通过request.GET获取url中的page

八. django模板语言特殊标记(重点内容)

1. 取字符串的值

def index(request):

return render(request, 'index/index.html', {'username': '一问奈何'})

{{ username }}

# 一问奈何

2. 取列表的值

def index(request):

# return render(request, 'index/index.html', {'username': '一问奈何'})

return render(request, 'index/index.html', {'username': ['thanlon','Kiku']})

直接通过索引

{#

{{ username }}

#}

{{ username }}

{{ username.0 }}

{{ username.1 }}

通过循环遍历

{% for item in username %}

{{ item }}

{% endfor %}

Django框架从入门到应用

3. 取字典的值

def index(request):

return render(request, 'index/index.html', {

'user_dict': {'name': '一问奈何', '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'},

]

})

通过索引取值

{{ user_list_dict.0.id}}--{{ user_list_dict.0.name}}

{{ user_list_dict.1.id}}--{{ user_list_dict.0.name}}

通过循环取值

{% for row in user_list_dict %}

{{ row.id }}--{{ row.name }}

{% endfor %}

Django框架从入门到应用

九. 学生信息管理系统-数据库表的结构设计

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

-> );

十. 学生信息管理系统-查询班级信息列表与添加班级信息

1. 向班级表中添加数据

mysql> insert class values(null,'软件工程'),(null,'计算机科学与技术');

2. 查询班级信息

新建文件夹app01,并在文件夹中新建views.py

Django框架从入门到应用

配置路径,修改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函数(路径对应此函数)中写查询班级信息的逻辑代码

from django.shortcuts import render, redirect

import pymysql

def classes(request):

'''

查询班级id、班级名称

:param request:对象相关的数据

:return:渲染后的模板

'''

# 创建连接

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='wwwnxl', db='test')

# 创建游标

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 执行sql语句

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

添加无锡×××医院 http://www.bhnkyixue.com/

{% for row in classes_list %}

{{ row.id }}

{{ row.title }}

{% endfor %}

运行程序后,访问http://127.0.0.1:8000/classes/可以查看到页面效果:

Django框架从入门到应用

3. 添加班级信息

配置路径,修改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

添加班级

班级名称:

Django框架从入门到应用

在views.py的add_class函数中写添加学生班级信息的逻辑代码

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/')

程序正常运行后,在班级信息页面(http://127.0.0.1:8000/classes/)中点击添加按钮,进入添加班级信息界面(http://127.0.0.1:8000/add-class/)。提交添加的班级信息后,自动跳转到班级信息页面。

十. 学生信息管理系统-删除班级信息

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/')

浏览器向服务端发送删除数据的请求,服务端接收请求删除数据后向浏览器发送响应,告诉浏览器重定向到/classes/。服务端向浏览器发送响应的响应头中有location:http://127.0.0.1:8000/classes/,即是:告诉浏览器向此链接发送一次请求。

十一. 学生信息管理系统-编辑班级信息

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') # 放到请求体

nid = request.GET.get('nid') # 放到请求头

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:

编辑班级信息

班级名称:

{# #}


本文题目:Django框架从入门到应用
标题路径:http://scyanting.com/article/iijppe.html