Django 系列博客(一)

前言

学习了 python 这么久,终于到了Django 框架。这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 Django框架的安装到使用一步步的学习,这系列博客不会像前端的那样水了(立个 flag),希望可以成为高质量的博客。那么本篇博客介绍 Django 的安装以及如何在电脑上运行第一个 Django 应用。

Django 的安装

Django 的安装很简单,在 win 和 mac 上面都可以使用 pip 安装命令安装,也可以通过 pycharm 安装,或者下载文件在命令行使用安装工具安装。

接下来我在 ubuntu 上安装做示例。

在这里还安装了一个依赖包 pytz。这是用来做时区转换的一个第三方库。

其他平台的 pip 安装方式一样,不过要选用 python3的对应 pip 来安装,因为现在的 Django 版本已经不支持 python2了。

虚拟环境的安装

什么是虚拟环境

  • 对真实的 python 解释器的一个拷贝版本
  • 事实有效,可以独立存在并运行解释 python 代码
  • 可以在计算机上拷贝多个虚拟环境

为什么要使用虚拟环境

  • 保证真实环境的纯净性
  • 框架的多版本共存
  • 方便做框架的版本迭代
  • 降低多框架共存的维护成本

安装虚拟环境

  1. 通过 pip 安装虚拟环境库

因为我之前已经下载好了,所以这里直接显示请求已经完成,并且后面是安装的绝对路径。

  1. 前往目标文件夹

这个文件夹是你用来保存虚拟环境的文件夹,该文件夹一旦确定就不要轻易更改。

这个 py3-env1是创建的一个纯净虚拟环境。

  1. 创建纯净的虚拟环境
virtualenv 虚拟环境名 (py3-env2)
  1. 终端启动虚拟环境
cd py3-env1\Scripts
activate
  1. 进入虚拟环境下的 python 开发环境
python3
  1. 关闭虚拟环境
deactivate
  1. 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 连接称之为一个事务,过程可以分为四步

  1. 客户端与服务端建立连接
  2. 客户端发生一个 HTTP 协议指定格式的请求
  3. 服务端接收请求后,回应一个 HTTP 协议指定格式的响应
  4. 客户端将服务端的响应展现给用户

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'

Django 系列博客(一)的更多相关文章

  1. Django 系列博客(十六)

    Django 系列博客(十六) 前言 本篇博客介绍 Django 的 forms 组件. 基本属性介绍 创建 forms 类时,主要涉及到字段和插件,字段用于对用户请求数据的验证,插件用于自动生成 h ...

  2. Django 系列博客(十四)

    Django 系列博客(十四) 前言 本篇博客介绍在 html 中使用 ajax 与后台进行数据交互. 什么是 ajax ajax(Asynchronous Javascript And XML)翻译 ...

  3. Django 系列博客(十三)

    Django 系列博客(十三) 前言 本篇博客介绍 Django 中的常用字段和参数. ORM 字段 AutoField int 自增列,必须填入参数 primary_key=True.当 model ...

  4. Django 系列博客(十二)

    Django 系列博客(十二) 前言 本篇博客继续介绍 Django 中的查询,分别为聚合查询和分组查询,以及 F 和 Q 查询. 聚合查询 语法:aggregate(*args, **kwargs) ...

  5. Django 系列博客(十一)

    Django 系列博客(十一) 前言 本篇博客介绍使用 ORM 来进行多表的操作,当然重点在查询方面. 创建表 实例: 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日 ...

  6. Django 系列博客(十)

    Django 系列博客(十) 前言 本篇博客介绍在 Django 中如何对数据库进行增删查改,主要为对单表进行操作. ORM简介 查询数据层次图解:如果操作 mysql,ORM 是在 pymysql ...

  7. Django 系列博客(九)

    Django 系列博客(九) 前言 本篇博客介绍 Django 模板的导入与继承以及导入导入静态文件的几种方式. 模板导入 模板导入 语法:``{% include '模板名称' %} 如下: < ...

  8. Django 系列博客(八)

    Django 系列博客(八) 前言 本篇博客介绍 Django 中的模板层,模板都是Django 使用相关函数渲染后传输给前端在显式的,为了想要渲染出我们想要的数据,需要学习模板语法,相关过滤器.标签 ...

  9. Django 系列博客(七)

    Django 系列博客(七) 前言 本篇博客介绍 Django 中的视图层中的相关参数,HttpRequest 对象.HttpResponse 对象.JsonResponse,以及视图层的两种响应方式 ...

  10. Django 系列博客(六)

    Django 系列博客(六) 前言 本篇博客介绍 Django 中的路由控制部分,一个网络请求首先到达的就是路由这部分,经过路由与视图层的映射关系再执行相应的代码逻辑并将结果返回给客户端. Djang ...

随机推荐

  1. B树/[oracle]connect BY语句

    读大神的书,出现很多没有见过的函数和便捷操作,特此记录 connect by 之前没有接触过,为了学习这个语句,先了解一下B树数据类型是最好的方法. [本人摘自以下博客] https://www.cn ...

  2. pageHelper的使用步骤,省略sql语句中的limit

    1.引架包.注意版本问题 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId& ...

  3. C pointer again …

    记录一个比较基础的东东…… C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

  4. 急速安装lnmp 编译版本-wiki-shell脚本实现一键部署

    shell脚本lnmp.sh 环境:centos 6.5 .64位 #!/bin/bash yum install -y nano vim wget wget http://www.atomicorp ...

  5. prototype 和 __proto__

    /* * 1.构造函数里有属性及方法----->其构造的实例对象直接通过new构造时获得这些属性和方法 * 2.构造函数里的原型prototype----->这个原型对象:包括1).原型对 ...

  6. 《HTTP权威指南》6-代理

    Web的中间实体 HTTP的代理服务器既是Web服务器又是Web客户端,它既需要正确地处理从客户端发来的请求和连接,返回响应,有需要向服务器发送请求,并接受响应. 私有和共享代理 代理服务器可以是某个 ...

  7. 【转载】sql monitor

    来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/27067062/viewspace-2129635/ SQL Monitor Report 1. SQL Monit ...

  8. Windows 10 IoT Core 17083 for Insider 版本更新

    1月26日,微软发布了Windows 10 IoT Core 17083 for Insider版本更新,概括如下: 新特性:1. General bug fixes2. Enabled Flash ...

  9. Metasploit Framework(5)弱点扫描

    文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 当我们发现了目标机器开放的端口,开启的服务等等之后 就 ...

  10. Core 读取配置文件

    新建控制台 static void Main(string[] args) { Console.WriteLine("Hello World!"); //获取应用程序的当前工作目录 ...