Python Django WEB框架
Django WEB框架
1 基本WEB框架
import socket
server = socket.socket()
ip_port = ('127.0.0.1',8000)
server.bind(ip_port)
server.listen()
while True:
conn,addr = server.accept()
recv_msg = conn.recv(1024)
print(recv_msg)
conn.send(b'My First WEB Server')
conn.close()
在浏览器的URL输入框中输入:http://127.0.0.1:8000/
,浏览器返回My First WEB Server
。
服务器端窗口输出:
GET / HTTP/1.1
Host: 127.0.0.1:8000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4385.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
2 WSGI
如何才能让服务器能够执行动态的内容?一般会分为两部分:服务器程序和应用程序。
-
应用程序则负责具体的逻辑处理。一般是通过
Python
或者PHP
来处理,之后再把处理完的结果在提交到HTTP 服务器程序
。 -
HTTP服务器程序负责对socket服务器进行封装:将 HTTP 请求响应给客户端。
WSGI(Web Server Gateway Interface)
就是一种规范,它定义了使用 Python
编写的 web 应用程序
与 web服务器程序
之间的接口格式,实现 web 应用程序
与 web服务器程序
间的解耦。wsgi
类似是 Python
到 HTTP
的一条通道。类似还有 CGI、FastCGI
等。Apache、Nginx
等 HTTP服务器软件都是只负责处理 HTTP 的请求和响应,然后 Python、PHP
再通过类似 wsgi
这样的接口与之融合。
Python标准库
提供的独立WSGI服务器叫 wsgiref
,Django开发环境用的就是这个模块来做服务器。
2.1 HTML文档模板
此模板试用于第二章所有实例。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Title</title>
</head>
<body>
<h1>header1</h1>
<p>this is paragraph.</p>
<h1>{{ userinfo }}</h1>
<ul>
{% for k,v in userinfo.items() %}
<li>{{ k }}--{{ v }}</li>
{% endfor %}
</ul>
</body>
</html>
2.2 WSGI-基本配置
from wsgiref.simple_server import make_server
def application(environ, start_response):
"""
application 由wsgi服务器调用、函数对http请求与响应的封装
:param environ: 返回浏览器http请求信息 (dist)
:param start_response: WEB服务器响应客户端 (function)
传给HTTP服务器程序时,格式应为byte类型,并加上"[]"
:return:
"""
print(environ)
# 响应浏览器请求
start_response('200 ok', [('Content-Type', 'text/html'), ('k1', 'v1'), ('k2', 'v2')])
if environ['REQUEST_METHOD'] == 'GET' and environ['PATH_INFO'] == '/':
with open('dynamicWEB.html', 'rb') as f:
data = f.read()
return [data]
# 启动服务器 | 这个服务器负责与 wsgi 接口的 application 函数对接数据
httpd = make_server('127.0.0.1', 8000, application)
# 监听请求
print('Serving HTTP on port 8000...')
httpd.serve_forever()
2.3 WSGI 动态WEB实现:结合Jinja2
结合Jinja2,用从数据库中查询数据去替换HTML文档中的对应内容,最后发送给浏览器完成渲染。
#!/usr/bin/env python
# -*- coding:UTF-8 -*-
# Author: Fan Carey
# Version 1.0
# Created time:
# Description:
from wsgiref.simple_server import make_server
from jinja2 import Template
import pymysql
def user_data():
"""
连接数据库,从数据库中查询数据并返回
:return:
"""
db_conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='toor',
database='jinja2',
charset='utf8',
)
cursor = db_conn.cursor(pymysql.cursors.DictCursor)
sql_cmd = 'select * from userinfo;'
cursor.execute(sql_cmd)
user_tmp_data = cursor.fetchone()
print(user_tmp_data)
db_conn.commit()
cursor.close()
db_conn.close()
return user_tmp_data
def application(environ, start_response):
"""
application 由wsgi服务器调用、函数对http请求与响应的封装
:param environ: 返回浏览器http请求信息 (dist)
:param start_response: WEB服务器响应客户端 (function)
传给HTTP服务器程序时,格式应为byte类型,并加上"[]"
:return:
"""
# 响应浏览器请求
start_response('200 ok', [('Content-Type', 'text/html'), ('k1', 'v1'), ('k2', 'v2')])
user_dbdata = user_data()
if environ['REQUEST_METHOD'] == 'GET' and environ['PATH_INFO'] == '/':
with open('dynamicWEB.html', 'r', encoding='utf-8') as f:
data = f.read()
tmp = Template(data)
data = tmp.render({'userinfo': user_dbdata}).encode('utf-8')
return [data]
# 启动服务器 | 这个服务器负责与 wsgi 接口的 application 函数对接数据
httpd = make_server('127.0.0.1', 8000, application)
# 监听请求
print('Serving HTTP on port 8000...')
httpd.serve_forever()
mysql 数据库配置
CREATE DATABASE `jinja2` CHARACTER SET utf8;
use jinja2;
CREATE TABLE `userinfo` (
`id` int NOT NULL AUTO_INCREMENT,
`name` char(32) NOT NULL,
`age` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
3 Django
3.1 Django框架
-
MVC框架
MVC(Model View Controller)
:是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。 -
MTV框架
-
Django的MTV框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。
- Model(模型):负责业务对象与数据库的对象(ORM)
- Template(模版):负责如何把页面展示给用户
- View(视图):负责业务逻辑,并在适当的时候调用Model和Template
-
响应流程如下:
-
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oE7GilE1-1614902827236)(https://i.loli.net/2021/01/14/lI8JRP6kiUSX5ET.png)]
-
3.2 Django基本使用
以Windows环境为例
3.2.1 命令行模式下创建 Django 项目
1、安装Django:
$ pip3 install django==1.11.9
$ python -m django --version # 查看当前安装Django版本
2、创建一个Django项目
$ django-admin startproject mysite #创建了一个名为"mysite"的 Django 项目。
注:如果提示找不到该命令,请检查计算机环境变量中是否将以下目录添加至 Path 变量中。
C:\Users\username\AppData\Local\Programs\Python\Python38\Scripts
3、创建了以下文件
mysite/ # 根目录名称对 Django 没有影响
├── manage.py # 管理 Django 项目文件。通过它可以调用django shell和数据库,启动关闭项目与项目交互
└── mysite/ # 项目目录
├── __init__.py
├── settings.py # 配置文件
├── urls.py # URL 声明
├── wsgi.py # 运行在 WSGI 兼容的Web服务器上的入口
4、启动项目
$ python manage.py runserver
$ python manage.py runserver 127.0.0.1:8080
# 默认情况下,runserver 命令会将服务器设置为监听本机内部 IP 的 8000 端口。
如果设置服务器的监听本地访问 8080 端口:
$ python manage.py runserver 8080
如果设置服务器的监听所有访问 8080 端口:
$ python manage.py runserver 0:8000
5、创建一个应用
$ python manage.py startapp polls
在项目的配置文件settings.py中添加一个polls的配置
INSTALL_APPS = [
'polls', app名称
]
INSTALLED_APPS = [
# 方法1
'polls.apps.PollsConfig',
# 方法2
'polls',
]
3.2.2 使用 Pycharm 创建 Django 项目
- 打开Pycharm,选择New Project,在弹出窗口配置如下:
![image-20210114100717389](https://i.loli.net/2021/01/14/oZCneR8XPmTdLQ6.png)
-
运行新创建的项目
在打开的项目界面上,点击Pycharm 左上角的运行按钮的左边,选择刚刚创建的项目名称 “djangoProject” ,再点运行,即可启动。
或在Pycharm下面的终端输入:
python manage.py runserver
3.3 Django 配置文件修订
setting.py
1、template文件夹位置
设置template的'DIRS' 的值如下。
TEMPLATES = [
{
'DIRS': [os.path.join(BASE_DIR, "template")],
}
]
2、添加静态文件存放位置
STATIC_URL = '/static/' # HTML中使用的静态文件夹前缀
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
3、暂时禁用csrf中间件,方便表单提交测试。
MIDDLEWARE = [
# 'django.middleware.csrf.CsrfViewMiddleware',
]
4 配置一个项目
4.1 urls.py
默认匹配顺序是从上到下,且只要匹配上,便不再继续向下查找。
url(r'^admin/', admin.site.urls) # 第一个参数:匹配路径正则字符串,第二个参数:对应的视图函数
urlpatterns = [
# 网站首页显示URL路径下,开头与结尾都为空才可以匹配。
url(r'^$', views.home),
# 无名分组
url(r'^index/$', views.index),
# 位置参数
url(r'^articles/(\d{4})/(\d{1,2})/$', views.years_month_request),
# 有名分组
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', views.date_request),
# 默认值
url(r'^articles/(\d{2})/$', views.default_request),
# 匹配任意
url(r'', views.home),
]
4.2 views.py
对应urls.py所传回的参数。
# 无名分组
def index(request):
print(request.method)
if request.method == 'GET':
print(request.GET)
return render(request,'login.html')
else:
print(request.POST)
username = request.POST.get('username')
password = request.POST.get('password')
print(username,password)
if username== 'abname' and password=='abpass':
return HttpResponse('get correct username and password')
else:
return HttpResponse('get wrong information!')
# 位置参数
def years_month_request(request,year,month):
print('year-->: ',year)
print('month-->: ',month)
return HttpResponse(year+month)
# 有名分组
def date_request(request,day,month,year):
print('year-->: ',year)
print('month-->: ',month)
print('day-->: ',day)
return HttpResponse(year+month+day)
# 默认值
def default_request(request,year='2020',month='01'):
return HttpResponse("special year='2020',month='01'")
4.3 login.html
对应 views.py 下 index()方法所调用的模板。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Title</title>
</head>
<body>
<h1>welcome to log in.</h1>
<p>here is login.html</p>
<form action="" method="post">
<label for="username">username:
<input type="text" name="username" placeholder="username">
</label>
<label for="password">password:
<input type="password" name="password" placeholder="password">
</label>
<input type="submit" value="submit">
</form>
</body>
</html>