Django 系列博客(一)
程序员文章站
2022-05-04 13:43:50
Django 系列博客(一) 前言 学习了 python 这么久,终于到了Django 框架。这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 Django框架的安装到使用一步步的学习,这系列博客不会像前端的那样水了(立个 flag),希望可以成为高质量的博客。那么本篇博客 ......
django 系列博客(一)
前言
学习了 python 这么久,终于到了django 框架。这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 django框架的安装到使用一步步的学习,这系列博客不会像前端的那样水了(立个 flag),希望可以成为高质量的博客。那么本篇博客介绍 django 的安装以及如何在电脑上运行第一个 django 应用。
django 的安装
django 的安装很简单,在 win 和 mac 上面都可以使用 pip 安装命令安装,也可以通过 pycharm 安装,或者下载文件在命令行使用安装工具安装。
接下来我在 ubuntu 上安装做示例。
在这里还安装了一个依赖包 pytz。这是用来做时区转换的一个第三方库。
其他平台的 pip 安装方式一样,不过要选用 python3的对应 pip 来安装,因为现在的 django 版本已经不支持 python2了。
虚拟环境的安装
什么是虚拟环境
- 对真实的 python 解释器的一个拷贝版本
- 事实有效,可以独立存在并运行解释 python 代码
- 可以在计算机上拷贝多个虚拟环境
为什么要使用虚拟环境
- 保证真实环境的纯净性
- 框架的多版本共存
- 方便做框架的版本迭代
- 降低多框架共存的维护成本
安装虚拟环境
- 通过 pip 安装虚拟环境库
因为我之前已经下载好了,所以这里直接显示请求已经完成,并且后面是安装的绝对路径。
- 前往目标文件夹
这个文件夹是你用来保存虚拟环境的文件夹,该文件夹一旦确定就不要轻易更改。
这个 py3-env1是创建的一个纯净虚拟环境。
- 创建纯净的虚拟环境
virtualenv 虚拟环境名 (py3-env2)
- 终端启动虚拟环境
cd py3-env1\scripts activate
- 进入虚拟环境下的 python 开发环境
python3
- 关闭虚拟环境
deactivate
- pycharm的开发配置
添加:创建项目 -> project interpreter -> existing interpreter -> virtualenv environment | system interpreter -> 目标路径下的 python.exe 删除:setting -> project -> project interpreter -> show all
mac 电脑从第三步直接到最后一步就好
了解
# 创建非纯净环境: # -- virtualenv-clone 本地环境 虚拟环境名
# mac配置终端,在终端运行虚拟环境 # 在用户根目录下的.bash_profile(没有需手动创建)文件中设置 # alias 终端指令名(env-py3)='/library/virtualenv/虚拟环境名/bin/python3' # alias 终端指令名(env-pip3)='/library/virtualenv/虚拟环境名/bin/pip3'
http 协议
因为 django 框架应用层是采用的 http 协议,所以有必要了解 http 协议。
什么是 http 协议
- http(hypertext transport protocol) 是超文本传输协议,而 https 也归属于 http 协议,s 代表安全。
- 基于 tcp/ip协议基础上的应用层协议,底层实现仍为 socket
- 基于请求-响应模式:通信一定是从客户端开始,服务端接收到客户端一定会做出对应响应
- 无状态:协议不对任何一次通信状态和任何数据做保存
- 无连接:一次连接只完成一次请求-响应,请求-响应完毕后会立即断开连接。
http 工作原理
一次 http 连接称之为一个事务,过程可以分为四步
- 客户端与服务端建立连接
- 客户端发生一个 http 协议指定格式的请求
- 服务端接收请求后,回应一个 http 协议指定格式的响应
- 客户端将服务端的响应展现给用户
http 状态码
- 1开头:
- 2开头:
- 3开头:
- 4开头:
- 5开头:
请求报文
# 请求行 请求头 请求体 ''' post / http/1.1\r\n host: 127.0.0.1:8001\r\n connection: keep-alive\r\n upgrade-insecure-requests: 1\r\n user-agent: mozilla/5.0 (macintosh; intel mac os x 10_14_1) applewebkit/537.36 (khtml, like gecko) chrome/70.0.3538.110 safari/537.36\r\n accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n accept-encoding: gzip, deflate, br\r\n accept-language: zh-cn,zh;q=0.9,en;q=0.8\r\n \r\n usr=abc&pwd=123 '''
响应报文
# 响应行 响应头 响应体 ''' http/1.1 200 ok\r\n content-type:text/html\r\n \r\n login success '''
使用原生 socket 完成和浏览器的交互
目录结构
01_socket -- 01_client.html:前台通过form表单访问后台的页面 -- 01_login.html:后台测试渲染给前台的登录页面 -- 01_index.html:后台测试渲染给前台的主页 -- 01_server.py:后台服务器文件
因为 b/s架构的客户端已经由浏览器写好,所以只需要关注服务器端就ok。
服务器端代码
from socket import socket # 设置响应头(包含响应行) resp_header = b'http/1.1 200 ok\r\ncontent-type:text/html;charset=utf-8\r\n\r\n' # 连续两个\r\n表示响应头结束 # 设置服务器 socket 相关信息 server = socket() server.bind('', 8080) # 空字符串表示绑定本机 server.listen(5) print(('服务:http://localhost:8080')) while true: # 获取以 http 协议发来的请求 client, addr = server.accept() data = client.recv(1024) # 数据报文 包含请求行 请求头 请求体 print(data) client.send(resp_header) # /index => 响应主页 # /login => 登录页面 # 错误 => 404 # 数据 data, 字节形式 => 字符串形式 strdata = str(data, encodeing) # 解析请求的数据,分析得到路由 my_route = strdata.split('\r\n')[0].split(' ')[1] # 后台没有设置的路由,统统由404来处理 dt = b'404' # 设置的路由返回响应的页面文件 if my_route == '/index': with open('index 页面路径', 'rb') as f: dt = f.read() if my_route == '/login': with open('login 页面路径', 'rb') as f: dt = f.read() # /favicon.ico该请求是往后台请求标签图标 if my_route == '/favicon.ico': with open('favicon.ico', 'rb') as f: dt = f.read() # 服务器发送响应体 client.send(dt) # 一次循环,代表一次响应,也就是一次事务的完成,要关闭 http 请求连接 client.close()
修改返回数据,完善响应体
# 字符串 client.send(b'http/1.1 200 ok\r\n') client.send(b'\r\n') client.send(b'normal socket web')
# html代码,请求头要设置支持 html 代码 client.send(b'http/1.1 200 ok\r\n') client.send(b'content-type:text/html\r\n') client.send(b'\r\n') client.send(b'<h1>normal socket web</h1>')
# html文件(同级目录建立一个index.html页面) client.send(b'http/1.1 200 ok\r\n') client.send(b'content-type:text/html\r\n') client.send(b'\r\n') # 利用文件方式读取页面 with open('01_index.html', 'rb') as f: dt = f.read() client.send(dt)
拓展
修改接收数据,模拟后台路由
# 分析接收到的数据 data = client.recv(1024) # 保证接收到的数据作为字符串进行以下处理 data = str(data, encoding='utf-8') # 拆分出地址位 route = data.split('\r\n')[0].split(' ')[1] # 匹配地址,做出不同的响应 if route == '/index': with open('01_index.html', 'rb') as f: dt = f.read() elif route == '/login': with open('01_login.html', 'rb') as f: dt = f.read() else: dt = b'404' client.send(dt)
框架演变
目录结构
02_frame -- favicon.ico -- index.html -- manage.py
manage.py
import socket import pymysql # 响应头 resp_header = b'http/1.1 200 ok\r\ncontent-type:text/html\r\n\r\n' # 请求处理 def index(): # 以字节方式读取文件 with open('index.html', 'rb') as f: dt = f.read() return dt def ico(): with open('favicon.ico', 'rb') as f: dt = f.read() return dt def user(): # 数据库操作 conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root') cur = conn.cursor(pymysql.cursors.dictcursor) cur.execute('select * from user') users = cur.fetchall() print(users) users = '''%d:%s %d:%s''' % (users[0]['id'], users[0]['name'], users[1]['id'], users[1]['name']) return users.encode('utf-8') # 设置路由 urls = { # 请求路径与请求处理函数一一对应 '/index': index, '/favicon.ico': ico, '/user': user } # 设置socket def serve(host, port): server = socket.socket() server.bind((host, port)) print('start:http://' + host + ':' + str(port)) server.listen(5) while true: sock, addr = server.accept() data = sock.recv(1024) data = str(data, encoding='utf-8') print(data) route = data.split('\r\n')[0].split(' ')[1] resp = b'404' if route in urls: resp = urls[route]() sock.send(resp_header) sock.send(resp) sock.close() # 启服务 if __name__ == '__main__': serve('127.0.0.1', 8002)
项目演变
目录结构
03_proj -- template -- index.html -- user.html favicon.ico start.py urls.py views.py
index.html
<h1>{{ name }}</h1>
user.html
<table border="1"> <tr> <th>id</th> <th>name</th> <th>password</th> </tr> {% for user in users%} <tr> <td>{{user.id}}</td> <td>{{user.name}}</td> <td>{{user.password}}</td> </tr> {% endfor %} </table>
start.py
from wsgiref.simple_server import make_server from urls import urls def app(env, response): print(env) # 设置响应头 response("200 ok", [('content-type', 'text/html')]) route = env['path_info'] print(route) data = urls['error']() if route in urls: data = urls[route]() # 返回二进制响应体 return [data] if __name__ == '__main__': server = make_server('127.0.0.1', 8003, app) print('start:http://127.0.0.1:8003') server.serve_forever()
urls.py
from views import * urls = { '/index': index, '/favicon.ico': ico, '/user': user, 'error': error }
views.py
import pymysql # 利用jinja2来渲染模板,将后台数据传给前台 from jinja2 import template def index(): with open('templates/index.html', 'r') as f: dt = f.read() tem = template(dt) resp = tem.render(name='主页') return resp.encode('utf-8') def ico(): with open('favicon.ico', 'rb') as f: dt = f.read() return dt def user(): # 数据库操作 conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root') cur = conn.cursor(pymysql.cursors.dictcursor) cur.execute('select * from user') users = cur.fetchall() print(users) with open('templates/user.html', 'r') as f: dt = f.read() tem = template(dt) resp = tem.render(users=users) return resp.encode('utf-8') def error(): return b'404'
上一篇: 多态及多态性和鸭子类型
下一篇: [日常] Go语言圣经-匿名函数习题2
推荐阅读
-
业内*屏幕!一加9系列首批搭载LTPO柔性屏:刷新13项记录
-
在Parallel中使用DbSet.Add()发现的一系列多线程问题和解决思路详解
-
我的第一篇博客[Usaco2006 Mar]Mooo 奶牛的歌声
-
基于django的个人博客网站建立(四)
-
PHP与正则表达系列之一: PHP中的正则表达式_PHP教程
-
RabbitMQ系列(一)rabbitmq简介
-
springboot源码分析系列(一)--核心注解@SpringBootApplication
-
javascript - 新手想在短期内写一个个人博客,是用php还是用nodejs?
-
微服务系统架构设计系列 - RateLimiter - 1. 限流器简介与一般算法
-
iPhone 11系列缺失5G“挤牙膏”遭看衰 华为Mate30系列这一波又稳了