手撸web框架即引入框架思想,wsgierf模块,动静态网页,模板语法jinja2,python三大主流web框架,django安装,三板斧
手撸web框架
web框架
什么是web框架? 暂时可理解为服务端。
软件开发架构
- C/S架构
- B/S架构
# 后端
import socket
server = socket.socket() # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8000)) # IP协议,以太网协议,arp协议...
server.listen(5) # 监听,池的概念...
while True:
conn, addr = server.accept()
data = conn.recv(1024)
conn.send(b'hello word')
conn.close()
HTTP协议
"""
HTTP协议: 数据传输是明文
HTTPS协议: 数据传输是密文
websocket协议:数据传输是密文
"""
HTTP四大特性
- 基于请求响应
- 基于TCP、IP作用于应用层之上的协议
- 无状态
- 短/无连接
HTTP数据格式
- 请求首行
- 请求头
- 请求体
HTTP响应状态吗
- 1xx
- 2xx : 200
- 3xx : 重定向
- 4xx : 403,404
- 5xx : 500
基于上述大致回顾,得出结论,代码没有遵循HTTP协议,加入HTTP相关参数。
# 后端
import socket
server = socket.socket() # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8000)) # IP协议,以太网协议,arp协议...
server.listen(5) # 监听,池的概念...
while True:
conn, addr = server.accept()
data = conn.recv(1024)
conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
conn.close()
深入解析客户端返回数据,此时提出一个需求,要用在客户端输入127.0.0.1:8000/index
时浏览器页面返回不再是hello world
,而是输入的后缀名,如:index。
思路:拿到用户输入的后缀,用其做判断。
上图红框中显示的是所有请求头相关的信息。
# 用户客户端输入的后缀在第一个斜杠后方显示。
b'GET / HTTP/1.1\r\n
# 后端
import socket
server = socket.socket() # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001)) # IP协议,以太网协议,arp协议...
server.listen(5) # 监听,池的概念...
"""
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8000\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "macOS"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36\r\n
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\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest:
"""
while True:
conn, addr = server.accept()
data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
data = data.decode('utf8') # 此时,data为字符串类型
print(type(data))
conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
conn.close()
输出:
<class 'str'>
那么,如何获取字符串中特定的内容?
-
正则
-
若字符串有规律可以使用切割。
我们注意到字符串开头均头空格,先试用spilt(' ')
切割空格
while True:
conn, addr = server.accept()
data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
data = data.decode('utf8') # 此时,data为字符串类型
res = data.spilt(' ')
print(res)
conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
conn.close()
想要的元素为列表的第二个,索引为[1]的位置,那么如何获取列表中索引为[1]的元素即用户输入的url后缀?显而易见了。
while True:
conn, addr = server.accept()
data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
data = data.decode('utf8') # 此时,data为字符串类型
current_path = data.split(' ')[1] # 获取用户输入的网址后缀
print(current_path)
conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello word')
conn.close()
加入判断,使用用户输入不同后缀,返回不同内容:
# 后端
import socket
server = socket.socket() # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001)) # IP协议,以太网协议,arp协议...
server.listen(5) # 监听,池的概念...
"""
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8000\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "macOS"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36\r\n
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\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest:
"""
while True:
conn, addr = server.accept()
data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
data = data.decode('utf8') # 此时,data为字符串类型
conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 基于HTTP为流式协议
current_path = data.split(' ')[1] # 获取用户输入的网址后缀
if current_path == '/index':
conn.send(b'index')
elif current_path == '/login':
conn.send(b'login')
else:
conn.send(b'hello word')
conn.close()
既然可以返回不同的内容,那么可否能返回不用页面???
# 后端
import socket
server = socket.socket() # 不传参数TCP,三次握手四次挥手,osi七层
server.bind(('127.0.0.1', 8001)) # IP协议,以太网协议,arp协议...
server.listen(5) # 监听,池的概念...
"""
防止代码看来冗余,删除
"""
while True:
conn, addr = server.accept()
data = conn.recv(1024) # 由于此时的data为二进制数据类型,需要先转字符类型
data = data.decode('utf8') # 此时,data为字符串类型
conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
current_path = data.split(' ')[1] # 获取用户输入的网址后缀
if current_path == '/index':
# conn.send(b'index')
with open(r'myhtml.html','rb') as f:
conn.send(f.read())
elif current_path == '/login':
conn.send(b'login')
else:
conn.send(b'hello word')
conn.close()
纯手撸web框架不足之处:
- 代码重复
- 手动处理HTTP格式数据,只能拿到URL后缀信息,其他数据获取繁琐(数据格式一样处理的代码也大致相同,重复写代码)。
- 未解决并发问题
借助于wsgiref模块
from wsgiref.simple_server import make_server
def run():
pass
if __name__ == '__main__':
make_server()
control+鼠标左键点击make_server():
def make_server(
host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
):
"""Create a new WSGI server listening on `host` and `port` for `app`"""
server = server_class((host, port), handler_class)
server.set_app(app)
return server
# host : 服务端IP,port : 服务端端口 app : ?
编写wsgiref
from wsgiref.simple_server import make_server
# 再给run函数加括号调用时加两个形参
def run(env,response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回给浏览器的数据
"""
print(env)
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever() # 启动服务端
"""
将实时监听127.0.0.1:8080地址,只要有客户端链接,
都会交给run函数处理即为(加括号触发run函数的运行)
"""
报错的原因是代码未写全。
from wsgiref.simple_server import make_server
# 再给run函数加括号调用时加两个形参
def run(env,response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回给浏览器的数据
"""
print(env)
response('200 OK',[]) # 返回数据,响应首行,响应头
return [b'hello wsgiref']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever() # 启动服务端
"""
将实时监听127.0.0.1:8080地址,只要有客户端链接,
都会交给run函数处理即为(加括号触发run函数的运行)
"""
此时用户后缀无论写什么都会触发run方法,验证了只要有客户端链接,发送请求,都会交给run函数处理即为(加括号触发run函数的运行)。
抛出请求,无论客户输入什么,浏览器页面都返回用户输入。
思路,找到用户输入返回的键
代码:
from wsgiref.simple_server import make_server
# 再给run函数加括号调用时加两个形参
def run(env, response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回给浏览器的数据
"""
response('200 OK', []) # 返回数据,响应首行,响应头
current_path = env.get('PATH_INFO') # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
if current_path == '/index':
return [b'index']
elif current_path == '/login':
return [b'login']
else: # 如果后缀找不到,弹出404页面,即针对404页面也可以做响应的处理
return [b'404 error']
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever() # 启动服务端
"""
将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
都会交给run函数处理即为(加括号触发run函数的运行)
"""
纯手撸和wsgiref对比:
wsgiref只需要写业务逻辑和获取数据。
如果有成百上千的后缀难道要写成丢的elif?
from wsgiref.simple_server import make_server
def index():
return 'index'
def login():
return 'login' '三个函数'
def error():
return '404 error'
# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
urls = [
('/index', index), '对应关系'
('/login', login)
]
# 再给run函数加括号调用时加两个形参
'匹配关系'
def run(env, response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回给浏览器的数据
"""
response('200 OK', []) # 返回数据,响应首行,响应头
current_path = env.get('PATH_INFO') # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
# 提前定义一个变量,存储匹配到的函数名
func = None
for url in urls: # 此时的url是一个个元祖()
if current_path == url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break # 匹配到一个后 立刻结束for循环
# 也有可能for循环结束后func依旧为None
if func:
res = func()
else:
res = error()
# 统一封装,编码
return [res.encode('utf-8')]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8080, run)
server.serve_forever() # 启动服务端
"""
将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
都会交给run函数处理即为(加括号触发run函数的运行)
"""
再给函数传参,env
,是否就意味着可以拿到 客户端返回的数据,并在此基础之上做处理。并且若要添加功能需要在index,login,error
三个函数中操作即可,但是代码层面来讲太过冗余且杂乱。
安装不同的功能拆成不同的py文件
- urls.py
- views.py
匹配关系:
基于wsgiref.py
from wsgiref.simple_server import make_server
from urls import urls
from views import *
# 再给run函数加括号调用时加两个形参
def run(env, response):
"""
:param env: 请求相关的所有数据
:param response: 响应相关的所有数据
:return: 返回给浏览器的数据
"""
response('200 OK', []) # 返回数据,响应首行,响应头
current_path = env.get('PATH_INFO') # 拿到当前用户输入的后缀,判断后缀的不同返回不同的内容
# 提前定义一个变量,存储匹配到的函数名
func = None
for url in urls: # 此时的url是一个个元祖()
if current_path == url[0]:
# 将url对应的函数名赋值给func
func = url[1]
break # 匹配到一个后 立刻结束for循环
# 也有可能for循环结束后func依旧为None
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() # 启动服务端
"""
将实时监听127.0.0.1:8080地址,只要有客户端链接,发送请求
都会交给run函数处理即为(加括号触发run函数的运行)
"""
urls.py :对应关系
# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
# url 与 函数的对应关系
from views import *
urls = [
('/index', index),
('/login', login)
]
views.py:业务逻辑
# 业务逻辑
def index(env):
return 'index'
def login(env):
return 'login'
def error(env):
return '404 error'
测试:
正常
现在如果客户要增加一个后缀xxx,要求浏览器返回xxx,只需要修改urls和views即可。
urls
urls = [
('/index', index),
('/login', login),
('/xxx', xxx)
]
views.py
# 业务逻辑
def index(env):
return 'index'
def login(env):
return 'login'
def error(env):
return '404 error'
def xxx(env):
return 'xxx'
那么如果需要创建多个HTML呢?难道Pycharm的左侧要出现N个HTML文件?可以创一个文件夹存放。
templates
将所有的HTML文件都防止与templates中
测试,只需要变动views.py 即可
新创建一个HTML文件。
myxxx.html
<body>
<h1>一剑霜寒十四州</h1>
</body>
views.py
def xxx(env):
with open(r'templates/myxxx.html','r',encoding='utf8') as f:
return f.read()
借助于wsgiref模块
根据功能的不同,划分不同的文件和文件夹。
- urls.py >>> 路由(指URL后缀:http://127.0.0.1:8080/xxx)与视图函数(也是函数,处理业务逻辑的)对应关系
- views.py >>> 存放视图函数(后端业务逻辑)
- templates >>> 存放HTML文件
安装功能的不同拆分后,后续添加功能只需要在urls.py书写对应关系然后去views.py书写业务逻辑即可。
动静态网页
- 静态网页
页面上的数据写死,亘古不变 - 动态网页
数据实时获取:
1.后端获取当前时间,展示到HTML
2.数据从数据库中获取展示到HTML页面
动态网页制作:后端获取当前时间,展示到HTML
views.py
import datetime
def get_time(env):
current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
# 如何将后端获取到的数据"传递"给html文件?
with open(r'templates/mytime.html','r',encoding='utf8') as f:
data = f.read()
# data就是以对字符串
data = data.replace('asdasdad',current_time) # 在后端将html页面处理好之后再返回前端
return data
urls.py
urls = [
('/index', index),
('/login', login),
('/xxx', xxx),
('/get_time',get_time)
]
mytime.html
<body>
asdasdad
</body>
如何将一个字典传递给html文件,并且可以在文件上方便快捷的操作字典数据
模板语法值jinja2模块
安装:
pip3 install jinja2
views.py
from jinja2 import Template
def get_dict(env):
user_dic = {'username':'junjie','age':18,'hobby':'play'}
with open(r'templates/get_dict.html','r',encoding='utf8') as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user=user_dic)
# 给get_dict.html传递了一个值 页面上通过变量名user就能拿到user_dict
return res
urls.py
from views import *
urls = [
('/index', index),
('/login', login),
('/xxx', xxx),
('/get_time', get_time),
('/get_dict', get_dict)
]
get_dict.html
<body>
<h1>我是一个页面</h1>
{{ user }}
</body>
jinja2 html 的字典取值方式 : jinja2的模板语法
只在后端起作用
get_dict.html
<body>
<h1>我是一个页面</h1>
{{ user }} <!--获取到后端的传值-->
{{ user.get('username')}}
{{ user.age }}
{{ user['hobby'] }}
</body>
后端获取数据库中数据展示到前端页面
访问一个url,后端前往数据库拿数据,通过jinja2模板语法传到页面,再发给浏览器渲染。
urls.py
# 定义函数,每个url将会对应非常多的功能,比如登录注册... 以下只是举例,简化了。
# url 与 函数的对应关系
from views import *
urls = [
('/index', index),
('/login', login),
('/xxx', xxx),
('/get_time', get_time),
('/get_dict', get_dict),
('/get_user', get_user)
]
终端mysql创建库,表,并存入数据。
mysql> create database day59;
mysql> create table userinfo(id int primary key auto_increment,username varchar(16),password int,hobby varchar(16));
mysql> insert into userinfo(username,password,hobby) values('jason',123,'study'),('junjie',321,'play'),('tony',111,'生蚝'),('tom',222,'丝袜');
mysql> select * from userinfo;
+----+----------+----------+--------+
| id | username | password | hobby |
+----+----------+----------+--------+
| 1 | jason | 123 | study |
| 2 | junjie | 321 | play |
| 3 | tony | 111 | 生蚝 |
| 4 | tom | 222 | 丝袜 |
+----+----------+----------+--------+
4 rows in set (0.00 sec)
views.py
import pymysql
def get_user(env):
# 前往数据库中获取数据 传递给html页面,借助于模板语法 发送给浏览器
conn = pymysql.connect(
host= '127.0.0.1',
port= 3306,
user='root',
password='xJNN0315',
db='day59',
charset='utf8',
autocommit=True # 自动提交
)
# 字典格式
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = 'select * from userinfo'
affect_rows = cursor.execute(sql)
data_list = cursor.fetchall() # 输出格式: [{},{},{}]
# 将获取到的数据传递给html文件
with open(r'templates/get_data.html','r',encoding='utf8')as f:
data = f.read()
tmp = Template(data)
res = tmp.render(user_list=data_list) # user_list 变量名想取什么都行
return res
get_data.html
<body>
{{ user_list }}
</body>
如何将这一个个数据放到html文件中?并以表格的形式展示?
get_data.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<!--模板语法同样支持for循环-->
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1 class="text-center">用户数据</h1>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>password</th>
<th>hobby</th>
</tr>
</thead>
<tbody>
{% for user_dict in user_list %}
<tr>
<td>{{ user_dict.id }}</td>
<td>{{ user_dict.username }}</td>
<td>{{ user_dict.password }}</td>
<td>{{ user_dict.hobby }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
此时页面就属于动态页面,数据库增,该,删,全部互联,页面刷新即可。
自定义简易版本web框架请求流程图
wsgiref 模块做了两件事
1.请求来的时候解析http格式的数据,封装成大字典
2.响应走的时候给数据打包成符合http格式 再返回给浏览器
python三大主流web框架
- Django
- flask
- tornado
Django
特点:大而全,自带功能特别特别特别多。
不足:有时,过于笨重。
flask
特点:小而精,自带的功能特别特别特别少,第三方模块特别特别特别的多,如果将flask第三方的模块加起来完全可以飞过Django,并且也越来越像Django。
不足:较于依赖第三方的开发者,兼容性问题
tornado
特点:异步非阻塞,支持高并发,可以开发游戏服务器。
不足:当前而言不足暂时我不会。
web框架可以分成三个部分
A : socket部分
B : 路由与视图函数对应关系(路由匹配)
C : 模板语法
Django
A : 用的wsgiref
B : 自身
C : 自身
flask
A : 用的wekzeug,内部还是wsgierf
B : 自身
C : 用的jinja2
tornado
A : 自身
B : 自身
C : 自身
注意事项
想要电脑正常运行django项目必须满足以下三个条件。
- 1.计算机的名称不能含有中文
- 2.一个python窗口只开一个项目
- 3.项目中所有文件也尽量不要含有中文
- Python解释器尽量使用3.4~3.6之间
(如果项目报错,点击最后一个报错信息,去源码中把逗号删掉)
Django版本问题
- 1.x
- 2.x
- 3.x
公司之前用的1.8,慢慢过渡到1.11版本,有些项目使用到了2.0
Django官网:https://www.djangoproject.com/download/
Django安装
pip3 install jango==1.11.11
# 检测是否安装成功
django-admin
若已安装其他版本,无需自己卸载,直接重新安装,会自动卸载原有版本
django基本操作
- 命令行操作
- pycharm操作
命令行
创建django项目
django-admin startproject 项目名
django应用
Django是一款专门用来开发app的web框架
Django 框架就类似于一所大学,app就类似大学里面各个学院,一个app就是一个独立模块。
如开发淘宝:
订单相关
用户相关
投诉相关
..功能模块
一个app对应不同的功能
主要文件介绍:
-mysite文件夹 : 自定义Django项目名
--mysite : 文件夹
---settings.py : 项目的配置文件
---urls.py : 路由与视图函数的对应关系(路由层)
---wsgi.py : wsgiref模块
--mange.py : django的入口文件
--db.sqlite3 : django自带的sqlite3数据库(小型数据库,功能不是很多,还有bug)
--app01文件夹
---admin.py : django后台管理
---apps.py : 注册使用
---migrations文件夹 : 所有的数据库迁移记录(类似于日志)
---models.py : 数据库相关的 模型类(orm)
---test.py : 测试文件
---views.py : 视图函数(视图层)
Pycharm
方式一:
方式二:
命令行与pycharm创建区别
命令行创建不会自动生成templates文件夹,需要自己手动创建,而pycharm会自动创建,并且pycharm还会自动在配置文件中配置对应的路径。
pycharm 创建 settings.py 文件中
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')] # 拼接当前文件夹templates路径
,
'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',
],
},
},
]
命令行创建
需要手动添加[os.path.join(BASE_DIR, 'templates')]
以及 手动创建templates文件夹
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
}
]
注意:创建的应用一定要去配置文件中注册
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' # 简写
]
创建出来的应用第一步先去配置文件中注册。
简单的看下配置文件有什么配置
# 当前项目路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 上线之后改为Flase
DEBUG = True
# 上线之后可写*表所有
ALLOWED_HOSTS = []
# 注册的app(功能模块)
INSTALLED_APPS
# django中间件
MIDDLEWARE
# HTML文件存放路径配置
TEMPLATES
# 项目指定的数据库
DATABASES
django必备三板斧
- HttpResponse
- render
- redirect
HttpResponse:返回字符串类型
举例:
djangoday02/urls
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 自定义对应关系,路由与视图函数对应关系
url(r'^index/', views.index)
]
app01/views.py
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def index(request):
"""
:param request: 请求相关所有数据对象,比之前的env功能更多。
:return:
"""
return HttpResponse("嘿嘿嘿")
结论:HttpResponse 返回字符串类型。
render:返回HTML文件
app01/views.py
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def index(request):
"""
:param request: 请求相关所有数据对象,比之前的env功能更多。
:return:
"""
"""
自动前往templates寻找HTML文件
djangoday02/settings.py中TEMPLATES路径作用
"""
return render(request,'myifrst.html')
结论:render 返回HTML文件
redirect:重定向
views.py
from django.shortcuts import render,HttpResponse,redirect
# Create your views here.
def index(request):
"""
:param request: 请求相关所有数据对象,比之前的env功能更多。
:return:
"""
return redirect('https://www.baidu.com/')
跳转至百度。