Django
1 自己构建web框架
1.1 基本web框架
import socket
server = socket.socket() # TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(1024)
print(data)
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
conn.send(b'Hello')
conn.close()
'''
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site: none\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\nSec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-Mode: no-cors\r\nSec-Fetch-Dest: image\r\nReferer: http://127.0.0.1:8080/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
'''
获取用户输入参数
http://127.0.0.1:8080/index
import socket
server = socket.socket() # TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(1024)
data = data.decode('utf-8')
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
current_path = data.split(' ')[1]
if current_path == '/index':
with open(r'./templates/index.html') as f:
conn.send(f.read())
conn.close()
1.2 基于wsgire模块
上面代码的不足:
- 代码重复,服务端代码基本一样;
- 手动处理http格式数据,只能拿到url后缀,获取其它数据步骤繁琐;
- 未处理并发问题。
wsgire模块可以实现web服务网关接口。
作用:
- 接收请求时对http协议格式的数据进行解析,将其封装成字典格式数据;
- 发送响应时会将数据打包成符合http协议格式的数据。
from wsgiref.simple_server import make_server
def run(env, response):
"""
:param env: 请求相关的数据,字典,wsgiref模块将请求相关数据封装成字典。
:param response: 响应相关的数据。
:return: 返回给浏览器的数据
"""
response('200 OK', []) # 响应首行 + 响应头
current_path = env.get('PATH_INFO')
if current_path == '/index':
return [b'index']
else:
return [b'404']
if __name__ == '__main__':
# 监听http://127.0.0.1:8080,将请求交给函数run处理,触发执行函数run。
server = make_server('127.0.0.1', 8080, run)
# 启动服务端
server.serve_forever()
wsgiref模块封装了socket代码,并处理了http协议。
1.3 代码封装目录规范
main.py
from wsgiref.simple_server import make_server
from urls import url_list
from views import *
def run(env, response):
response('200 OK', [])
current_path = env.get('PATH_INFO')
func = None
for each_url in url_list:
if current_path == each_url[0]:
func = each_url[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
from views import *
url_list = [
('/index', index),
('/login', login),
]
views.py
def index(env):
with open(r'./templates/index.html', 'r', encoding='utf-8') as f:
return f.read()
def login(env):
with open(r'./templates/login.html', 'r', encoding='utf-8') as f:
return f.read()
def error(env):
with open(r'./templates/error.html', 'r', encoding='utf-8') as f:
return f.read()
urls.py
路由(url的参数,例如/index)与视图函数对应关系。
views.py
存放视图函数,即主要的后端逻辑。
templates文件夹
存储html文件。
按照功能进行拆分后,后续添加功能只需要在urls.py中添加对应的关系,再去views.py中添加业务逻辑。
1.4 静态网页与动态网页
静态网页:数据在html页面上是固定的,不会发生变化;
动态网页:数据是从后端实时获取的,例如:
- 从后端获取当前时间并展示到html页面上;
- 后端从数据库中获取数据并展示到html页面上。
1.5 模板语法 jinjia2模块
从数据库中获取数据,在后端借助模板语法将数据交给html文件,最后发送给浏览器。
views.py
from jinjia2 import Template
import pymysql
def get_dict(env):
# user_dict = {'username': 'Tom', 'age': 20, 'gender': 'male'}
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='userinfo',
charset='utf8',
autocommit=True
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql_str = 'SELECT * FROM userinfo'
cursor.execute(sql_str)
data_list = cursor.fetchall() # [{}, {}, {}]
with open(r'templates/get_data.html', 'r', encoding='utf-8') as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user_list=data_list)
# get_data.html可以通过user_list获取data_list。
return res
get_data.html
<body>
<!-- 模版语法
{{ user_dict }}
{{ user_dict.get('username') }}
{{ user_dict['username'] }}
{{ user_dict.username }}
-->
<!-- 模版语法支持循环 -->
<table>
<thead>
<th>Username</th>
<th>Age</th>
<th>Gender</th>
</thead>
<tbody>
{% for user_dict in user_list %}
<tr>
<td>{{ user_dict.get('username') }}</td>
<td>{{ user_dict['age'] }}</td>
<td>{{ user_dict.gender }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
注意,模版语法是在后端起作用的,即在views.py的视图函数中将html文本进行处理后再交给前端。
1.6 自定义web框架流程图
2 Django介绍
2.1 Python三大主流web框架
- django
优点:大而全,自带功能非常丰富;
缺点:过于笨重。 - flask
优点:小而精,自带功能非常少,支持flask的第三方模块非常多。如果将这些第三方的模块汇总起来,flask的功能完全可以超过django,也越来越像django;
缺点:依赖于第三方模块,可能会出现第三方模块的兼容性问题。 - tornado
优点:异步非阻塞,支持高并发,甚至可以用于开发游戏服务器;
没有明显缺点。
框架主要由三部分组成:
- socket部分;
- 路由与视图函数对应关系(路由匹配部分);
- 模板语法。
框架 | socket部分 | 路由匹配部分 | 模板语法部分 |
---|---|---|---|
django | wsgiref模块 | 自己 | 自己 (可能不如jinjia2模块) |
flask | werkzeug模块 (内部是wsgiref模块) | 自己 | jinjia2模块 |
tornado | 自己 | 自己 | 自己 |
2.2 启动django项目注意事项
- 计算机名称不能有中文;
- 一个pycharm窗口只开一个项目;
- 项目里面所有的文件也尽量不要出现中文;
- python解释器版本建议使用3.4~3.6。
(如果项目报错,可以尝试点击最后一个报错信息,去源码中删掉逗号。
django版本问题
1.X和2.X本身差距不大,主要以1.X为主,
3.X还处于开发中(2020年),功能可能不完善,不建议使用。
之前用的是1.8版本,之后慢慢过渡到1.11版本,有一些新项目使用2.0版本。
pip3 install django==1.11.11
验证是否安装成功
django-admin
出现
Type 'django-admin help <subcommand>' for help on a specific subcommand.
Available subcommands:
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
runserver
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).
2.3 基本操作
2.3.1 创建django项目
在终端先切换目录
D:\>cd PycharmProjects
创建django项目
D:\PycharmProjects>django-admin startproject DemoSite01
在当前路径下出现文件夹DemoSite01
D:\PYCHARMPROJECTS\DEMOSITE01
| manage.py
|
\---DemoSite01
settings.py
urls.py
wsgi.py
__init__.py
2.3.2 启动django项目
先切换到项目目录下
D:\PycharmProjects>cd DemoSite01
D:\PycharmProjects\DemoSite01>python manage.py runserver
使用浏览器登录http://127.0.0.1:8000/
也可以自定义ip地址和port号。
D:\PycharmProjects\DemoSite01>python manage.py runserver 127.0.0.1:9000
2.3.3 创建应用app
django是一款专门用来开发app的web框架,其中一个app就是一个独立的功能模块。
D:\PycharmProjects\DemoSite01>python manage.py startapp app01
使用pycharm创建app
pycharm中,Tools选项中选择Run manage.py Task。
默认快捷键:Ctrl + Alt + R
manage.py@DemoSite01 > startapp app01
pycharm中,在Edit Configurations中可以修改端口号。
D:\PYCHARMPROJECTS\DEMOSITE01
| manage.py
|
+---app01
| | admin.py
| | apps.py
| | models.py
| | tests.py
| | views.py
| | __init__.py
| |
| \---migrations
| __init__.py
|
\---DemoSite01
| settings.py
| urls.py
| wsgi.py
| __init__.py
|
\---__pycache__
settings.cpython-38.pyc
__init__.cpython-38.pyc
2.3.4 主要文件介绍
DemoSite01项目文件夹
名称 | 功能 |
---|---|
manage.py | django的入口文件 |
settings.py | 配置文件 |
urls.py | 存放路由与视图函数的对应关系 (路由层) |
wsgi.py | wsgiref模块 |
db.sqlite3 | django自带的sqlite3数据库 |
app01应用文件夹
名称 | 功能 |
---|---|
admin.py | django后台管理 |
apps.py | 注册使用 |
migrations文件夹 | 数据库迁移记录 |
models.py | 数据库相关的模型类(orm) |
tests.py | 测试文件 |
views.py | 视图函数 (视图层) |
备注
urls.py中
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
^用于确定待匹配文本的开始位置,$用于确定待匹配文本的结束位置。
即'r'^admin/'可以匹配'admin/ + 任意字符',
而'r'^admin/$'只可以匹配'admin/'。
2.3.5 配置文件settings.py
- 配置templates文件夹路径
使用命令行创建app时不会自动创建templates文件夹,
使用pycharm会自动创建templates文件夹,并自动在配置文件中配置对应路径。
settings.py
使用pycharm创建
TEMPLATES = [
'DIRS': [os.path.join(BASE_DIR, 'templates')],
]
使用命令行创建
TEMPLATES = [
'DIRS': [],
]
因此使用命令行创建django项目需要修改配置文件,指定templates文件夹的路径。
'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 注册新应用
新创建应用后,需要首先去配置文件settings.py中进行注册。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config', # 全写
'app02', # 简写
]
使用pycharm创建项目时,pycharm可以选择创建一个app并自动完成注册。
2.3.6 视图函数重要的三个功能
views.py中的视图函数可以实现以下三个功能。
from django.shortcuts import render, HttpResponse, redirect
- HttpResponse
返回字符串类型数据。
return HttpResponse(‘Hello’) - render
返回html页面。
return render(request, ‘test.html’)
向html页面传值
# 方式1
user_dict = {'username': 'Tom', 'password': 123}
return render(request, 'test.html', {'data': user_dict, 'timeout': 20})
# 方式2
return render(request, 'test.html', locals())
locals() 函数会以字典的形式返回当前位置所在名称空间中所有的局部变量。
- redirect
重定向。
return redirect(‘https://www.baidu.com/’)
return redirect(’/home/’)