惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
GRAHAM CLULEY
V
V2EX
WordPress大学
WordPress大学
博客园 - Franky
Last Week in AI
Last Week in AI
博客园 - 司徒正美
有赞技术团队
有赞技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
V
Visual Studio Blog
C
CERT Recently Published Vulnerability Notes
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
Attack and Defense Labs
Attack and Defense Labs
腾讯CDC
The Hacker News
The Hacker News
Hugging Face - Blog
Hugging Face - Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
J
Java Code Geeks
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
A
Arctic Wolf
量子位
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
雷峰网
雷峰网
博客园_首页
Google Online Security Blog
Google Online Security Blog
Spread Privacy
Spread Privacy
罗磊的独立博客
H
Hacker News: Front Page
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
TaoSecurity Blog
TaoSecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
IT之家
IT之家
The Cloudflare Blog
爱范儿
爱范儿
博客园 - 叶小钗
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 让浏览器下载文件 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例) 读《为什么学生不喜欢上学》 OpenAI Prompt Engineering 摘录和总结 读《打造真正的新产品》 VueJS 总结 Linux 自动挂载 alist 提供的webdav FreeBSD 使用 vm-bhyve 安装Debian虚拟机 FreeBSD 和 Linux 网卡聚合实现提速 GPT 帮我搞定了时区转换问题 长任务系统如何处理? macOS/Linux 编译 InputLeap 使用开源软KVM - synergy-core 解决 macOS 终端hostname一直变化问题 KVM 共享 Intel 集成显卡 PromQL 备忘 读《格鲁夫给经理人的第一课》 读《打开心智》 为什么要把复杂的联表操作拆成多个单表查询? 红包系统的设计 MySQL Index Condition Pushdown Optimization Go mod 简明教程 OpenWRT 使用 Android/iOS USB 网络 搭建旁路由 Golang gRPC 错误处理 编写可维护的单元测试代码 OAuth 2 详解(六):Authorization Code Flow with PKCE OAuth 2 详解(五):Device Authorization Flow OAuth 2 详解(三):Resource Owner Password Credentials Grant OAuth 2 详解(四):Client Credentials Flow OAuth 2 详解(二):Implict Grant Flow OAuth 2 详解(一):简介及 Authorization Code 模式 ElasticSearch 学习笔记 三种git流程以及发版模型 错误处理实践 权限模型(RBAC/ABAC) OIDC(OpenID Connect) 简介 任务队列简介 PostgreSQL 操作笔记 使用Drone CI构建CI/CD系统 Golang migrate 做数据库变更管理 使用PostgreSQL做搜索引擎 Nginx 源码阅读(三): 连接池、内存池 Nginx 源码阅读(二): 请求处理 Nginx 源码阅读(一): 启动流程 Go 泛型简明教程 KVM 显卡穿透给 Windows 使用 HTTP Router 处理 Telegram Bot 按钮回调 使用反射(reflect)对结构体赋值 GIN 是如何绑定参数的 你好 2022(2021 年终总结) 用Go导入大型CSV到PostgreSQL 使用 OpenWRT 搭建软路由 使用软KVM切换器 barrier 共享键鼠 SQL 防注入及原理 使用 gomock 测试 Go 代码 gevent不是黑魔法(二): gevent 实现 gevent不是黑魔法(一): greenlet 实现 用 entgo 替代 gorm 应用内使用crontab不是那么方便 单测时要不要 mock 数据库? Sentry 自建指南 用selenium完成自动化任务 用闲置的安卓手机做垃圾电话短信过滤 推荐三个时间管理工具 一次事故反思 当JS遇到uint64:JS整数溢出问题 SQLite3 存储以及ACID原理 Redis源码阅读:pub/sub实现 Redis源码阅读:zset实现 Redis源码阅读:bitmap 位图的运算 Redis源码阅读:set是怎么做交并集运算的?
Web开发系列(五):form, json, xml
Jiajun Huang · 2017-10-17 · via Jiajun的技术笔记

旧石器时代:表单

很久以前的web开发是怎么一个工作模式呢?那时候的前端不像现在的前端,那时候的前端基本上就是熟练CSS和HTML就可以了,JS要求其实 也不高,开发流程是这样的,前端先写好静态页面,然后丢给后端来套模板,那么问题来了,如果发现页面上的样式要改怎么办?

  • 方法一:前端到后端的电脑上来改
  • 方法二:前端改好之后,后端重新套模板,然后各种渲染

如果前端水平高,一次性写出无bug代码,那还好说,如果前端水平不行,哈哈哈哈哈哈哈哈,就等着哭吧。

那怎么处理用户数据呢?以前流行jQuery,一般是在button上绑定事件,用户提交的时候,jQuery用AJAX向后端发送一个form表单,当然 发送之前前端可能会对数据进行校验,但是无所谓,后端还是要校验,后端一般拿到数据之后,除了校验还要做类型转换。为什么呢?

参考 这篇博客 ,我们的form表单传给后端的时候是没有 类型信息的,全都是字符串,所以我们要把取出来的参数做强制转型,此外还要检验参数是否存在等。

所以代码长得有点像这样:

from flask import Flask, request, abort
app = Flask(__name__)


@app.route("/")
def hello():
    user_id = request.args.get("user_id")
    passwd = request.args.get("passwd")

    if not (user_id and passwd):
        abort(401)

    user_id = int(user_id)
    # 略略略


if __name__ == "__main__":
    app.run()

因此就有了一个东西,叫做表单校验工具,是啊,谁乐意老是写这么多重复的校验代码,说实话,之前没用过第三方的表单校验,都是 公司内部造的轮子,但是Python界还是有一个非常出名的表单校验工具:WTForms, 不过说实话,我没用过,不太好作评价。但是表单校验工具长得都差不多:

  • 定义好这个参数是否必须
  • 定义好这个参数的类型
  • 定义好这个参数的要求,例如范围,长度,可否为空等

然后根据定义好的这些用响应的validators进行校验,如果失败就返回错误或者抛出对应的异常。此外,表单校验工具一般都会把form表单 的数据根据所定义好的类型转换成对应的数据。

新的曙光,前后端分离

一直一直一直到了近些年,大前端时代,前后端分离这种架构慢慢流行起来。流行的原因是什么呢?因为移动互联网,没人愿意给前端渲染 一遍模板,又给app开发一套代码,麻烦得要命,所以我们只提供API,前端自己渲染数据。近年来更是有RESTFul啊这些概念,以前写接口 那都是xml来作为传输格式的。

JSON,全名是JavaScript Object Notation,就是把js里的集中基本数据类型,拿出来表示数据,其实这货在Python里可以很好的映射, 例如JSON的array对应Python的List,object对应dict,blablabla。一个简单的JSON长得像这样:

{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}

像Python这样的动态类型语言写这些可爽了,直接 json.loads 然后开干,但是像Go这样的强类型静态语言就不行了,要先定义好 JSON的结构,然后慢慢解析,虽然Go也可以强行解析成一个 interface{},但是interface走天下也不是太好。

xml

如果你调用过微信的接口你就会发现,微信接口竟然还用xml。。。xml也是一种数据表现形式,长得跟html有点像,各种tag和嵌套,用来 表示复杂的关系时还可以用用,不过这年头用xml的确实不多了。给个例子你就知道为什么没人愿意用了,上面的JSON的例子,用xml表示 是这样:

<!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
 <glossary><title>example glossary</title>
  <GlossDiv><title>S</title>
   <GlossList>
    <GlossEntry ID="SGML" SortAs="SGML">
     <GlossTerm>Standard Generalized Markup Language</GlossTerm>
     <Acronym>SGML</Acronym>
     <Abbrev>ISO 8879:1986</Abbrev>
     <GlossDef>
      <para>A meta-markup language, used to create markup
languages such as DocBook.</para>
      <GlossSeeAlso OtherTerm="GML">
      <GlossSeeAlso OtherTerm="XML">
     </GlossDef>
     <GlossSee OtherTerm="markup">
    </GlossEntry>
   </GlossList>
  </GlossDiv>
 </glossary>

emm…看到都不想碰

对比:模板渲染和前后端分离

最后我们来对比一下模板渲染和前后端分离。模板渲染有什么好处呢?一般来说,模板渲染的性能会高一些,因为模板渲染的原理是, 渲染器把模板文件“编译”成对应的程序,这个程序里的代码就是模板里想表述的代码,然后各种字符串拼接,所以模板实际上最后变成了 程序代码。其实你要是看到很多Java程序员写模板,他们还有很多for循环里put一个标签之类的,那就是在手写模板。

而前后端分离性能理论上应该要稍差,因为首先html下发到浏览器之后,浏览器才去获取首页的数据,然后渲染,当然,现在也有用 nodejs在服务器端请求api之后渲染,其实也差不多,总之呢,前后端分离之后,前端和后端请求数据这一步是省不掉的。

既然前后端分离这么灵活,模板渲染有啥好处?第一,容易被爬虫抓到,第二,服务端可以丢到缓存里,这样性能更高。而前后端分离 则恰恰相反,爬虫不一定能抓到,很大程度上要依靠浏览器进行缓存。但是呢,前后端分离大大的解耦了前端程序员和后端程序员, 只要约定好了API,各自更改各自的程序,互不影响。

现在我基本不写模板渲染了,哈哈哈。

讲完,收工 :)