Flask

文章导读:本文主要是利用socket来编写一个简单的服务器,通过对浏览器地址栏中输入的地址信息来调用相应的函数,并将用户信息【用户名, 密码】存储到txt文件中,在在登入界面提交表单时能对用户信息进行验证。

功能:用户注册, 用户登入, 网页信息显示, 用户信息存储。

[这个程序还存在一些小问题]

目录结构:

utils.py文件:

import timedef log(*args, **kwargs):"""对print函数进行封装,并输出时间。:param args::param kwargs::return:"""format = '%b %d %Y %H:%M:%S >'# time.time()返回unix timevalue = time.localtime(int(time.time()))# time.strftime()把时间变为str格式输出dt = time.strftime(format, value)print(dt, args, kwargs)

Server.py文件:

import socketfrom utils import log
from request_class import Requestfrom routes import route_static
from routes import route_dictdef parsed_path(path):"""分离出path and query:param path::return:"""# /search# /search?kd=python&name=Kevin"""{kd : pythonname : Kevin}"""index = path.find('?')if index == -1:return path, {}else:path, query_string = path.split('?', 1)# kd=python&name=Kevinargs = query_string.split('&')query = {}for arg in args:k, v = arg.split('=')query[k] = vreturn path, querydef error(code=404):"""错误页面:param code::return e:"""e = {404: 'GET HTTP/1.1 404 NOT FOUND\r\n\r\n<h1>Not Found</h1>',}return e.get(code, b'')def response_for_path(path):"""调用path相对应的函数:param path::return:"""path, query = parsed_path(path)request.path = pathrequest.query = querylog('path: {}, query: {}'.format(request.path, request.query))r = {'/static': route_static,}r.update(route_dict)response = r.get(path, error)return response(request)request = Request()def run(host='', port=3000):"""启动服务器:param host::param port::return:"""log('start at {}, {}'.format(host, port))# 使用with防止程序崩溃with socket.socket() as s:# 绑定端口s.bind((host, port))while True:# 监听s.listen(5)connection, address = s.accept()# 为了简单,暂时这里只接受1024字节r = connection.recv(1000)r = r.decode('utf-8')log('ip: {}\n request: {}'.format(address, r))# 因为 chrome 会发送空请求导致 split 得到空 list# 所以这里判断一下防止程序崩溃if len(r.split()) < 2:continue# GET / HTTP/1.1\r\n   ....path = r.split()[1]request.method = r.split()[0]request.body = r.split('\r\n\r\n', 1)[1]# 用response_for_path函数来调用path对应的函数response = response_for_path(path)# 发送数据connection.sendall(response)# 关闭连接connection.close()def main():"""主函数:return:"""# 生成配置文件并运行config = dict(host='',port=3000,)run(**config)if __name__ == '__main__':main()

routes.py文件:

from user import User
from message import Message
from utils import logmessage_list = []def template(name):"""读取template文件夹中的文件:param name::return f:"""# 这里的文件路径为我电脑上的路径path = '/home/kevin/programe/python/flask_xiao/day3/templates/' + namewith open(path, 'r', encoding='utf-8') as f:return f.read()def route_index(request):"""主页:param request::return:"""header = 'HTTP/1.1 200 OK\r\nContent-Type=text/html\r\n'body = template('index.html')r = header + '\r\n' + bodyreturn r.encode(encoding='utf-8')def route_login(request):"""登入函数:param request::return r:"""header = 'HTTP/1.1 200 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' + bodyreturn r.encode(encoding='utf-8')def route_register(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_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' + bodyreturn r.encode(encoding='utf-8')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_listheader = 'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n'# body = '<h1>消息版</h1>'body = template('html_basic.html')msgs = '<br>'.join([str(m) for m in message_list])body = body.replace('{{messages}}', msgs)r = header + '\r\n' + bodyreturn r.encode(encoding='utf-8')def route_static(request):"""静态资料处理函数,处理图片:param request::return img:"""filename = request.query.get('file', 'doge.gif')#这里的文件路径为我电脑上的路径path = '/home/kevin/programe/python/flask_xiao/day3/static/' + filenamewith 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 imgroute_dict = {'/': route_index,'/login': route_login,'/register': route_register,'/message': route_message,
}

request_class.py文件:

import urllib.parseclass Request(object):"""定义一个Request类用来保存请求的数据"""def __init__(self):# 默认为GET请求self.method = 'GET'self.path = ''self.query = {}self.body = ''def form(self):# username=Kevin&password=123# 将body拆分开来# 变为username=Kevin password=123#这里有个小bug没有解决body = self.body.split('&')# 将其他格式转变为网页可以认识的格式,如空格转换为%20args = urllib.parse.unquote(body)f = {}for arg in args:k, v = arg.split('=')f[k] = vreturn f

db文件夹:

__init__.py文件:

from file_save_load import save, load
from utils import logclass Model(object):"""存储数据的基类"""#类方法的调用是 类名.方法@classmethoddef db_path(cls):"""因为classmethod有个参数为class所以可以调用名字:return path:"""class_name = cls.__name__path = '{}.txt'.format(class_name)return path@classmethoddef all(cls):"""得到一个类所有存储的实例:return:"""path = cls.db_path()models = load(path)ms = [cls.__new__(m) for m in models]return msdef save(self):"""save 函数用于把一个 Model 的实例保存到文件中"""models = self.all()log('models', models)models.append(self)# __dict__ 是包含了对象所有属性和值的字典l = [m.__dict__ for m in models]path = self.db_path()save(l, path)def __repr__(self):class_name = self.__class__.__name__properties = ['{}: ({})'.format(k, v) for k, v in self.__dict__.items()]s = '\n'.join(properties)return '< {}\n{} >\n'.format(class_name, s)

file_save_load.py文件:

import jsonfrom utils import logdef save(data, path):"""存储数据的函数data表示dict or listpath 表示存储路径:param data::param path::return:"""# json 是一个序列化/反序列化list/dict 的库# indent表示缩进# ensure_ascii表示保存中文字符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 or list:param path::return:"""with open(path, 'r', encoding='utf-8') as f:s = f.read()log('Load: ', s)return json.load(s)

user.py文件:

from __init__ import Modelclass User(Model):"""用户类继承Model"""def new(self, form):"""获取用户名与密码:param form::return:"""self.username = form.get('username', '')self.password = form.get('password', '')def validate_login(self):"""用户登入:return username, password:"""return self.username == 'Kevin' and self.password == '123'def validate_register(self):"""用户注册:return:"""return len(self.username) > 2 and len(self.password) > 2

message.py文件:

from __init__ import Model# 定义一个 class 用于保存 message
class Message(Model):def new(self, form):self.author = form.get('author', '')self.message = form.get('message', '')


templates文件夹:

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 rows cols 都是属性, 用处上课讲 --><textarea name="message" rows="8" cols="40"></textarea><textarea name="author" rows="8" cols="40"></textarea><!-- button type=submit 才可以提交表单 --><button type="submit">POST 提交</button></form><form action="/messages" method="get"><textarea name="message" rows="8" cols="40"></textarea><button type="submit">GET 提交</button></form>{{messages}}</body>
</html>

index.html文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>主页</title>
</head>
<body><h1>Hello Kevin</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>

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>

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>

flask_萧井陌视频学习(三)相关推荐

  1. flask_萧井陌视频学习(二)

    Flask 文章导读:本文主要是利用socket来编写一个简单的服务器,通过在网页地址栏输入的请求来调用与之对应的函数来解析对应的网页文档. # 主函数 def main():"" ...

  2. flask_萧井陌视频学习(一)

    Flask 文章导读:本文主要是介绍运用python语言中的Socket包来写简单的客户端和服务器. 客户端的创建: import socket#创建套接字 #AF_INET ipv4, SOCK_S ...

  3. 萧井陌java_萧井陌编程入门指南

    萧井陌编程入门指南下载!萧井陌编程入门指南pdf是一款为学习JAVA用户打造的视频教程.需要学习JAVA的用户赶紧下载,此套JAV编程思想的课程适合想要自学java的同学们,课程抽丝拨茧,层层推进,让 ...

  4. 看萧井陌b站直播第一集的收获,附代码

    看了萧井陌在b站直播的录播第一集,收获颇大,遂记录一下: 直播中使用的语言是JavaScript,我之前学web后台的时候,对js有一个简单的了解,因为学过C++和Java,所以看录播的时候虽然有些语 ...

  5. python面试大全 萧井陌_Python就该这么学?!

    分享零基础学习Python的经验,15年4月份正式开始学习Python语言的,入门读物是一本书<父与子编程>. 关于第1点,我需要进一步强调:因为我目标非常明确,利用Python进行Web ...

  6. 知乎萧井陌大神《编程入门指南v1.3》思维导图

      毕业之后才发现大学的基础课程是多么的关键,有幸在知乎上看到萧井陌大神的文章,打算将涉及的内容学一学,下午花了1h用思维导图将文章梳理如下,希望对大家有帮助(图片太大,因此进行了分割): 原文链接: ...

  7. 萧井陌java课程资料_群大佬里分享的知乎萧大萧井陌24课前端视频,需要的自取...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 世界上最后一个人类躺在床上,他的床边是名女性机器人. 机器人身怀任务,她要观察人类这个濒危物种,并研究他们的思想. 现在任务即将结束,人类太老了,他正在等 ...

  8. python面试大全 萧井陌_有多少人按@萧井陌大神给出的Python+Flask路线找到工作了?...

    python+Flask(之后转Django)的答一发. 背景先上,30+岁,零基础,自学.不管是年龄还是工作背景还是教育经历都同web开发无关.也没有名校背景. 二月初开始学,五月拿到offer.三 ...

  9. python面试大全 萧井陌_知乎萧井陌大神Python Flask实战课程

    [课程内容] 第1章 网址组成.端口.HTTP协议.web服务器 第2章 作业讲解.服务器框架.html和getpost传递参数 第3章 基本框架.框架解释.model解释 第4章 cookie讲解. ...

最新文章

  1. 自制Ghost XP SP3 启动光盘(一)
  2. matlab柱状斜线_Matlab:柱状图饼状图填充不同条纹
  3. idea关联mysql失败_Server returns invalid timezone. Go to ‘Advanced‘ tab and set ‘serverTimezon‘
  4. 【干货】网易严选大数据架构.pdf(附下载链接)
  5. 移动路由器刷linux,Linux小课堂开课了(7)-三线IP刷路由-移动-联通-电信
  6. mac下缺乏make wget怎么办?
  7. CCSP2020比赛太原理工学子再创佳绩
  8. JAVA并发之多线程基础(3)
  9. 读《scikiit-learn机器学习》第七章_决策树
  10. SAP HANA SQL获取当前日期
  11. 华为手机隐藏app图标_3秒钟轻松隐藏华为手机桌面图标!不需要下载安装第三方软件哦!...
  12. AMOS分析技术:结构方程模型的拟合度评价指标
  13. 【蓝牙串口无线烧写程序】适用于STM32F103和STM32F107的Bootloader
  14. texlive的安装
  15. 百度千言-中文文本相似度实战
  16. 树莓派CM4 USB不能使用
  17. 接口测试常用工具及测试方法(入门篇)
  18. 《LoadRunner 12七天速成宝典》—第2章2.2节解决乱码
  19. 百度优化系列之快速收录
  20. STM32 cudeIDE使用J-link下载程序

热门文章

  1. Java中Could not find the main class.program will的解决方法(转)
  2. 开源中国 2014 最受关注开源软件排行榜 TOP 50
  3. C++--输出:保留两位小数
  4. PS2 格兰蒂亚3 汉化研究
  5. EFI系统分区必须挂载到/boot/efi其中之一
  6. 小学生有必要学机器人编程吗
  7. t568a/t568b的线序
  8. (2.4)【服务型木马-winshell】最小木马:使用方法
  9. GUID partition table (GPT) 磁盘分区表详解
  10. 使用npm命令启动http-server服务时指定端口