[TOC]
>[success] # 尝试搭建框架
~~~
我们所要做的工程目录划分
1.一个db 文件夹用来存储数据
2.一个models 文件夹用来操作数据
3.一个static文件夹用来保存静态文件
4.一个templates 用来保存html
5.一个routes.py 用来做路由映射
6.一个server.py 用来做启动文件
7.一个utils.py 用来配置log
~~~
>[info] ## 编写记录log -- utils.py
~~~
import time
def log(*args, **kwargs):
# time.time() 返回 unix time
format = '%Y/%m/%d %H:%M:%S'
value = time.localtime(int(time.time()))
dt = time.strftime(format, value)
print(dt, *args, **kwargs)
~~~
>[info] ## 编写服务器入口文件--server.py
~~~
1.Request 类进行,保存不同路由映射函数信息
2.response_for_path 处理run中获取的地址进行路由映射
3.run 方法用来启动server服务器
~~~
>[danger] ##### Request 保存路由映射对应请求信息类
~~~
1.初始化参数 method 记录每一个映射路由的请求
2.path 记录每一个路由的地址路径
3.body 保存每一个路由的body 内容主要针对post
4.query 记录每一个get请求链接上的参数 配合parsed_path 函数
5.form 用来处理post 请求参数urllib.parse .unquote(v) 处理v 是因为post 的时候空格是+
~~~
~~~
class Request:
def __init__(self):
self.method = "GET"
self.path = ""
self.body = ""
self.query = {}
def form(self):
args = self.body.split("&")
f = {}
for arg in args:
k, v = arg.split("=")
f[k] = urllib.parse .unquote(v)
return f
# 实例化对象
request = Reuqest()
~~~
>[danger] ##### parsed_path 处理get 请求
~~~
def parsed_path(path):
index = path.find("?")
if index == -1:
return path, {}
else:
path, query_string = path.split("?", 1)
args = query_string.split("&")
query = {}
for arg in args:
k, v = arg.split('=')
query[k] = v
return path, query
~~~
>[danger] ##### 编写一个异常处理的erro文件返回404
~~~
def error(request, code=404):
e = {
404: b'HTTP/1.1 404 NOT FOUND\r\n\r\n<h1>NOT FOUND</h1>',
}
return e.get(code, b'')
~~~
>[danger] ##### response_for_path 处理路由映射关系
~~~
1.parsed_path用来处理 get 请求方法,将get 请求方法清洗,返回地址和请求参数
2.return 返回的是将路由映射保存的request 对象传入到对应的映射方法
~~~
~~~
def response_for_path(path):
# 如果你是get
path, query = parsed_path(path)
request.path = path
request.query = query
r = {
"/static":route_static,
}
r.update(urls)
response = r.get(path, error)
return response(request)
~~~
>[danger] ##### run 启动服务器文件
~~~
def run(host='', port=3000):
# 在控制台打印端口,和服务器启动时间
log('start at', '{}:{}'.format(host, port))
# 使用 with 可以保证程序中断的时候正确关闭 socket 释放占用的端口
with socket.socket() as s:
s.bind((host, port))
while True:
s.listen(5)
connection, address = s.accept()
r = b""
buffer_size = 1024
while True:
r_connection = connection.recv(buffer_size)
r += r_connection
if len(r_connection) <= 1024:
break
r = r.decode('utf-8')
if len(r.split())<2:
continue
# 拆分原始数据 获取 请求方法和路径 GET / HTTP/1.1
path = r.split()[1]
request.method = r.split()[0]
# 利用"\r\n\r\n" 是将请求体分割格式,获取请求体
request.body = r.split("\r\n\r\n", 1)[1]
# 路由映射
response = response_for_path(path)
connection.sendall(response)
# 处理完请求, 关闭连接
connection.close()
~~~
>[info] ## 路由映射文件 -- routes.py
~~~
1.这个文件主要处理每一个,映射函数的请求
2.核对templates 文件的搭配
3.以及处理一些简单的模板
~~~
>[danger] ##### 处理读取HTML函数的 -- template
~~~
1.注意一定要对open 中的encoding 进行编码,win默认是gbk模式
~~~
~~~
def template(name):
path = "template/" + name
with open(path, "r",encoding='utf-8') as f:
return f.read()
~~~
>[danger] ##### 配置url 参数映射字典
~~~
urls = {
'/': route_index,
'/login': route_login,
'/register': route_register,
'/messages': route_message,
}
~~~
>[danger] ##### 编写静态文件的映射函数 -- route_static
~~~
def route_static(request):
"""
两种情况的处理
path, query = response_for_path('/static?file=doge.gif')
path '/static'
"""
filename = request.query.get('file', 'doge.gif')
path = 'static/' + filename
with open(path, 'rb') as f:
header = b'HTTP/1.1 200 OK\r\nContent-Type: image/gif\r\n'
img = header + b'\r\n'+ f.read()
return img
~~~
>[danger] ##### 编写第一个主页映射函数 -- route_index
~~~
def route_index(request):
"""
主页的处理函数, 返回主页的响应
"""
header = 'HTTP/1.1 210 VERY OK\r\nContent-Type: text/html\r\n'
body = template('index.html')
r = header + '\r\n' + body
return r.encode(encoding='utf-8')
~~~
>[danger] ##### 编写登录逻辑处理的---route_login
~~~
1.传的参数中的request 保存的是每一个函数的,请求时候的处理信息
2.如果是post 请求处理创建的Request 类中form 方法保存的body中的内容
3.利用replace 替代我们在html 中特殊格式化的数据,这个页面最后渲染不应该属于任何请求,而是所有请求处理的展示内
容改变
~~~
~~~
def route_login(request):
header = 'HTTP/1.1 210 VERY OK\r\nContent-Type: text/html\r\n'
if request.method == 'POST':
form = request.form()
u = User.new(form)
if u.validate_login():
result = '登录成功'
else:
result = '用户名或者密码错误'
else:
result = ''
body = template('login.html')
body = body.replace('{{result}}', result)
r = header + '\r\n' + body
return r.encode(encoding='utf-8')
~~~
>[danger] ##### 编写注册处理函数 --- route_register
~~~
def route_register(request):
header = 'HTTP/1.1 210 VERY OK\r\nContent-Type: text/html\r\n'
if request.method == 'POST':
# HTTP BODY 如下
# username=gw123&password=123
# 经过 request.form() 函数之后会变成一个字典
form = request.form()
u = User.new(form)
if u.validate_register():
u.save()
result = '注册成功<br> <pre>{}</pre>'.format(User.all())
else:
result = '用户名或者密码长度必须大于2'
else:
result = ''
body = template('register.html')
body = body.replace('{{result}}', result)
r = header + '\r\n' + body
return r.encode(encoding='utf-8')
~~~
>[danger] ##### 模拟简单的psot get请求 ---route_message
~~~
# message_list 存储了所有的 message
message_list = []
def route_message(request):
log('本次请求的 method', request.method)
if request.method == 'POST':
form = request.form()
msg = Message.new(form)
log('post', form)
message_list.append(msg)
# 应该在这里保存 message_list
header = 'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n'
body = template('html_basic.html')
# '#'.join(['a', 'b', 'c']) 的结果是 'a#b#c'
msgs = '<br>'.join([str(m) for m in message_list])
body = body.replace('{{messages}}', msgs)
r = header + '\r\n' + body
return r.encode(encoding='utf-8')
~~~
>[info] ## 编写数据处理文件夹 model
~~~
1.我们处理数据库的连接模块进行拆分,成三个小py文件
2.__init__.py用来编写model 的父类和数据存放方法
3.user.py 用来处理用户信息判断验证
4.message.py 用来处理信息验证
~~~
>[danger] # 编写__init__文件
~~~
1.class Model 类用来处理文件的保存和读取
--- 注意这个类几点说明
--- db_path 中使用了cls.__name__ 的方法,可以获取使用类的类名,因为类名和对象不同点在于,类名是唯一的,做成
父类后所有子类就变成唯一的
--- new 相当于创建了对应的类
--- all 是获取了所有储存文件的内容
--- save 将所有内容保存到文件目录中
2.save 方法用来保存文件信息
3.load 用来加载文件信息
~~~
~~~
def save(data, path):
"""
本函数把一个 dict 或者 list 写入文件
data 是 dict 或者 list
path 是保存文件的路径
indent 是缩进
ensure_ascii=False 用于保存中文
"""
s = json.dumps(data, indent=2, ensure_ascii=False)
with open(path, 'w+', encoding='utf-8') as f:
log('save', path, s, data)
f.write(s)
def load(path):
"""
本函数从一个文件中载入数据并转化为 dict 或者 list
path 是保存文件的路径
"""
with open(path, 'r', encoding='utf-8') as f:
s = f.read()
log('load', s)
return json.loads(s)
# Model 是用于存储数据的基类
class Model(object):
@classmethod
def db_path(cls):
classname = cls.__name__
path = 'db/{}.txt'.format(classname)
return path
@classmethod
def new(cls, form):
# 下面一句相当于 User(form) 或者 Msg(form)
m = cls(form)
return m
@classmethod
def all(cls):
"""
得到一个类的所有存储的实例
"""
path = cls.db_path()
models = load(path)
log('log', models)
ms = [cls.new(m) for m in models]
return ms
def save(self):
"""
save 函数用于把一个 Model 的实例保存到文件中
"""
models = self.all()
log('models', models)
models.append(self)
# __dict__ 是包含了对象所有属性和值的字典
l = [m.__dict__ for m in models]
log("lmodel", l)
path = self.db_path()
save(l, path)
def __repr__(self):
"""
对象的显示形式,__dict__ 返回的是初始化 参数
"""
classname = self.__class__.__name__
properties = ['{}: ({})'.format(k, v) for k, v in self.__dict__.items()]
s = '\n'.join(properties)
return '< {}\n{} >\n'.format(classname, s)
~~~
>[danger] 用来进行用户注册登录判断的 user.py
~~~
from models import Model
class User(Model):
def __init__(self, form):
self.username = form.get('username', '')
self.password = form.get('password', '')
def validate_login(self):
return self.username == 'gua' and self.password == '123'
def validate_register(self):
return len(self.username) > 2 and len(self.password) > 2
~~~
>[danger] 用来进行简单的post,get message.py
~~~
from models import Model
# 定义一个 class 用于保存 message
class Message(Model):
def __init__(self, form):
self.author = form.get('author', '')
self.message = form.get('message', '')
~~~
>[info] ## html 文件
>[danger] ##### login.html
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册登录页面</title>
</head>
<body>
<h1>登录</h1>
<form action="/login" method="post">
<input type="text" name="username" placeholder="请输入用户名">
<br>
<input type="text" name="password" placeholder="请输入密码">
<br>
<button type="submit">登录</button>
</form>
<h3>{{result}}</h3>
</body>
</html>
~~~
>[danger] ##### register.html
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<h1>注册</h1>
<form action="/register" method="post">
<input type="text" name="username" placeholder="请输入用户名">
<br>
<input type="text" name="password" placeholder="请输入密码">
<br>
<button type="submit">注册</button>
</form>
<h3>{{result}}</h3>
</body>
</html>
~~~
>[danger] ##### index.html
~~~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>吃瓜主页</title>
</head>
<body>
<h1>吃瓜</h1>
<a href="/login">Login</a>
<img src="/static?file=doge.gif"/>
<img src="/static?file=doge1.jpg"/>
<img src="/static?file=doge2.gif"/>
</body>
</html>
~~~
>[danger] ##### html_basic.html
~~~
<!DOCTYPE html>
<!-- 注释是这样的, 不会被显示出来 -->
<!--
html 格式是浏览器使用的标准网页格式
简而言之就是 标签套标签
-->
<!-- html 中是所有的内容 -->
<html>
<!-- head 中是放一些控制信息, 不会被显示 -->
<head>
<!-- meta charset 指定了页面编码, 否则中文会乱码 -->
<meta charset="utf-8">
<!-- title 是浏览器显示的页面标题 -->
<title>例子 1</title>
</head>
<!-- body 中是浏览器要显示的内容 -->
<body>
<!-- html 中的空格是会被转义的, 所以显示的和写的是不一样的 -->
<!-- 代码写了很多空格, 显示的时候就只有一个 -->
很 好普通版
<h1>很好 h1 版</h1>
<h2>很好 h2 版</h2>
<h3>很好 h3 版</h3>
<!-- form 是用来给服务器传递数据的 tag -->
<!-- action 属性是 path -->
<!-- method 属性是 HTTP方法 一般是 get 或者 post -->
<!-- get post 的区别上课会讲 -->
<form action="/messages" method="post">
<!-- textarea 是一个文本域 -->
<!-- name 属性, 用处上课讲 -->
<textarea name="message"></textarea>
<textarea name="author"></textarea>
<!-- button type=submit 才可以提交表单 -->
<button type="submit">POST 提交</button>
</form>
<form action="/messages" method="get">
<textarea name="message"></textarea>
<button type="submit">GET 提交</button>
</form>
{{messages}}
</body>
</html>
~~~
- 网络原理
- 为搭建框架做准备
- 简单认识网路
- 自定义模拟网站案例
- 优化最终框架
- 数据存储 -- data
- 用户个人信息存储 -- User.txt
- 路由映射 -- routes
- 处理用户信息 -- routes_static.py
- 保存静态文件 -- static
- templates -- html 集中处理模块
- 首页 -- index.html
- 登陆 -- login.html
- 用户注册页面 -- register
- 日志模块 -- log.gua.txt
- 启动文件--server.py
- orm处理 -- model.py
- 日志模块 -- utils.py
- 两种数据库类型
- 传统数据库了解篇
- 前端快速入门
- JS简单使用入门
- css简单快速入门
- DJANGO
- virtualenv-创建虚拟环境
- 项目结构
- django-admin中文配置
- django-打印sql语句
- django-基础
- 认识MVC和MTV
- Django--初识
- Django--初识案例
- Django-FBV/CBV
- Django--常用input 交互
- Django-url
- Django-url.py 配置
- Django-include 使用
- Django-url name
- Django-ORM
- ORM-数据库配置
- ORM-model字段
- ORM-model字段解释
- ORM-字段选项
- ORM-查询
- ORM-四种常用查询方法
- ORM-三种获取数据
- ORM-其他查询方式
- ORM-条件查询双线
- ORM-Q和F条件使用
- ORM-三种数据库交互
- 案例 -- 一对多
- ORM-技巧/常见问题
- ORM-N+1 问题
- ORM-并发的处理
- ORM-数量查询、
- ORM-正向反向查询
- ORM-基础案例一
- ORM-基础一对多案例
- Django-templates
- Django-模板的继承
- Django-模板的过滤
- Django-自定义模板的过滤
- Django-cookie
- Django-cookies 装饰器
- Djang-session
- Django-CSRF
- Django-中间件 -- 后续了解
- Django- 缓存 -- 没有深入了解
- Django-form
- From-ajax
- form-内部验证处理
- form-属性
- form-常用的标签字段
- form-常用的下拉和选择
- form-widget速查
- Django-ajax序列化
- Django-多种ajax写法
- ajax-原生写法
- ajax-$写法
- ajax-ifram
- Django-ajax图片上传
- ajax-原始写法
- ajax-正常写法
- iframe+form
- 实战写法
- Django-常用自编写组件
- Django-双菜单组合搜索
- Django - 多菜单组合搜索
- Django-分页
- django-综合基础
- 综合基础-render
- django-admin
- admin-页面配置
- admin-字段配置
- admin-编辑页面
- admin-forms验证
- admin-创建抽象类
- django-验证码
- 验证码-第三方生成库
- 验证码-view.py使用
- 验证码-注意引入Monaco.ttf
- django-用户注册
- 注册-form 模块
- 注册-views 模块
- 注册-html模块
- 注册-model模块
- django-用户登录三种
- session登录
- form-session 写法
- view-写法
- Html-写法
- model-写法
- 继承类登录
- 外键关联登录
- django-简单的student 管理案例
- app-urls.py
- app-models.py配置
- admin-admin.py配置
- app-form.py 和数据库关联的写法
- app-FBV_views.py
- app-CBV_views.py
- templates-index.html
- django-博客系统
- APP目录-models.py 创建
- APP目录-基础展示数据分析
- APP目录-基础数据展示cls
- ListView
- DetailView
- FormView
- 额外功能拓建
- 添加文章搜索/用户文章查询功能
- 增加一个友情链接
- 增加一个评论模块
- App-利用Bootstrap4 搭建样式
- 项目crm
- 思维导图
- perfectCRM-项目名字
- settings.py-配置
- view.py-登陆/登出函数
- crm-app文件
- model.py-表的创建
- admin.py-注册后台
- view.py-视图层
- static-静态文件
- css
- bootstrap.min.css
- dashboard.css
- ie10-viewport-bug-workaround.css
- signin.css
- fonts
- imgs
- js
- jquery.js
- bootstrap.min.js
- holeder.js
- ie10-viewport-bug-workaround.js
- ie-emulation-modes-warning.js
- plugins
- html模板文件-templates
- crm
- index.html-首页模板