第十二章 Django框架
12.1 服务器程序和应用程序
服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。
WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。
常用的WSGI服务器有uwsgi、Gunicorn,而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。
12.11 用wsgiref代替socket server
import time
from wsgiref.simple_server import make_server
def home(url): # 将返回不同的内容部分封装成函数
s = "this is {} page!".format(url)
return bytes(s, encoding="utf8")
def index(url):
return b'<h1>index page</h1>'
def user(url): # 不同的用户得到的页面上显示不同的时间
c_time = str(time.time())
with open("user.html", "r") as f:
data_s = f.read()
data_s = data_s.replace("@@xx@@", c_time)
return bytes(data_s, encoding="utf8")
url2func = [ # url和实际要执行的函数的对应关系
("/index/", index),
("/home/", home),
("/user/", user),]
def run_server(environ, start_response):# 按照wsgiref的要求定义一个run_server函数
start_response('200 OK',[('Content-Type','text/html;charset=utf8'),])#设置HTTP响应的状态码和头信息
url = environ['PATH_INFO'] # 取到用户输入的url
func = None
for i in url2func:
if url == i[0]:
func = i[1] # 拿到将要执行的函数
break
if func:
msg = func(url) # 执行对应的函数
else:
msg = b'<h1>404</h1>' # 找不到要执行的函数就返回404
return [msg, ] # 发送消息到客户端
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8090, run_server)
print("我在8090等你哦...")
httpd.serve_forever()
12.12 HTML模板渲染工具jinja2
user.html:
<body>
<table border="1">
<thead>
<tr>
<th>id</th>
<th>姓名</th>
<th>爱好</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.hobby}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
使用jinjia2替换HTML中的数据:
使用pymysql模块查询数据库获取数据,使用jinjia2替换HTML中的数据
模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容
import time
from wsgiref.simple_server import make_server
from jinja2 import Template
import pymysql
def user(url):
conn = pymysql.connect( # 从数据库里面去到所有的用户信息,
host='127.0.0.1',
port=3306,
user='root',
password='',
database='db6',
charset='utf8'
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute('select * from user')
ret = cursor.fetchall()
#print(ret)
with open("user.html", "r", encoding="utf8") as f:
data_s = f.read()
template = Template(data_s) # 生成一个模板文件实例
msg = template.render({"user_list": ret}) # 把数据填充到模板里面
return bytes(msg, encoding="utf8") url2func = [ # url和将要执行的函数的对应关系
("/index/", index),
("/home/", home),
("/user/", user),]
def run_server(environ, start_response): # 按照wsgiref的要求定义一个run_server函数
start_response('200 OK',[('Content-Type','text/html;charset=utf8'),])#设置HTTP响应的状态码和头信息
url = environ['PATH_INFO'] # 取到用户输入的url
func = None
for i in url2func:
if url == i[0]:
func = i[1] # 拿到将要执行的函数
break
if func:
msg = func(url) # 执行对应的函数
else:
msg = b'<h1>404</h1>' # 找不到要执行的函数就返回404
return [msg, ] # 发送消息到客户端
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8090, run_server)
print("我在8090等你哦...")
httpd.serve_forever()
12.2 Django基础必备三件套
用命令创建了一个名为"mysite"的Django 项目
django-admin startproject mysite
Django目录:
mysite/
├── manage.py # 管理文件
└── mysite # 项目目录
├── __init__.py
├── settings.py # 配置
├── urls.py # 路由 --> URL和函数的对应关系
└── wsgi.py # runserver命令就使用wsgiref模块做简单的 web server
用命令运行Django项目
python3 manage.py runserver 127.0.0.1:8000 #默认使用8000端口
模板文件配置:settings
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "template")], # template文件夹位置
'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',
],
},
},
]
静态文件配置:settings
STATIC_URL = '/static/' # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"), # 静态文件存放位置
]
12.21 HttpResponse
内部传入一个字符串参数,返回给浏览器
from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import HttpResponse, render, redirect
def index(request): #所有跟请求相关的数据都封装到了request这个参数里面
# 业务逻辑代码
return HttpResponse("这是index页面!")
12.22 render
除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数,将数据填充进模板文件,最后把结果返回给浏览器(类似于上面用到的jinja2)
def login(request):
# 自己去找HTML文件
# with open("templates/login.html", "r", encoding="utf8") as f:
# data = f.read()
# return HttpResponse(data)
# Django去找login.html文件,读取出来内容,返回给浏览器
return render(request, "login.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})
12.23 redirect
接受一个URL参数,表示跳转到指定的URL
def index(request):
# 业务逻辑代码
return redirect("/home/")
12.24 设置URL和函数的对应关系
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^home/', home),
url(r'^index/', index),
url(r'^login/', login),
]