Python前端系列—Flask+HTML
一、Python 前端开发概述
- Flask框架
- 前端开发:
HTML、CSS、JavaScript、JQuery、BootStrap
- 数据库:MySQL
- 前端开发:
- Web开发:Django 框架
1. 网站的本质
2. Flask 框架
(1). 前言
- 这里介绍Flask框架并不是为了利用Flask框架进行网页开发,而是利用这个介绍
HTML、CSS、JavaScript、JQuery、BootStrap
等相关内容,实际开发还是会使用Django框架
(2). 简单上手
- 第一步环境安装
进入Pycharm中,在终端命令行输入下面命令进行安装:pip install flask
- 第二步:创建简单的项目这里起名 “MySite”,并写入代码,查看运行效果
from flask import Flask # 导入包 app = Flask(__name__) #__name__前面说过,判断是不是程序入口 # http://127.0.0.1:9000/home @app.route('/home') #设置网址标签 def home(): #.... return "HOME" #返回字符串,也可以返回HTML文件等 if __name__ == '__main__': app.run(host='127.0.0.1', port=9000) # 运行,设置为主机IP,端口号任意,最好5000以上
- 第三步:运行查看结果:
运行后在终端命令行有 " http://127.0.0.1:9000/" 的网址:
点击进入后,在原来网址后加上/home
即可访问页面
(3). 函数返回的几种情况
-
情况一:根据Flask框架的规则搭建基本的开发架子 ——返回一个字符串
from flask import Flask # 导入包 app = Flask(__name__) #__name__前面说过,判断是不是程序入口 # http://127.0.0.1:9000/home @app.route('/home') #设置网址标签 def home(): #.... return "HOME" #返回字符串,也可以返回HTML文件等 if __name__ == '__main__': app.run(host='127.0.0.1', port=9000) # 运行,设置为主机IP,端口号任意,最好5000以上
-
情况二:HTML标签包裹数据返回 ——》浏览器返回,查看
from flask import Flask # 导入包 app = Flask(__name__) #__name__前面说过,判断是不是程序入口 # http://127.0.0.1:9000/home @app.route('/home') #设置网址标签 def home(): #.... return "<h1>中国电信</h1> <h6>中国联通</h6>" # HTML标签包裹数据返回 if __name__ == '__main__': app.run(host='127.0.0.1', port=9000) # 运行,设置为主机IP,端口号任意,最好5000以上
-
情况三:HTML标签包裹数据+ CSS样式 ——》浏览器返回,查看
- CSS : 层叠样式表
<h1 style = "color:red;">中国电信</h1> <h6>中国联通</h6>
from flask import Flask # 导入包 app = Flask(__name__) #__name__前面说过,判断是不是程序入口 # http://127.0.0.1:9000/home @app.route('/home') #设置网址标签 def home(): #.... return "<h1 style = "color:red;">中国电信</h1> <h6>中国联通</h6>" # HTML标签包裹数据+CSS if __name__ == '__main__': app.run(host='127.0.0.1', port=9000) # 运行,设置为主机IP,端口号任意,最好5000以上
- CSS : 层叠样式表
- 情况四:HTML标签包裹数据+ CSS样式 + JavaScript——》浏览器返回,查看
JavaScript,简称 js,可以让我们的标签动态和交互from flask import Flask # 导入包 app = Flask(__name__) #__name__前面说过,判断是不是程序入口 # http://127.0.0.1:9000/home @app.route('/home') #设置网址标签 def home(): #.... return "<h1 style = "color:red;" onclick = 'alert(111)'>中国电信</h1> <h6>中国联通</h6>" # # HTML标签包裹数据+CSS +JS if __name__ == '__main__': app.run(host='127.0.0.1', port=9000) # 运行,设置为主机IP,端口号任意,最好5000以上
(4). 直接返回HTML包裹数据+CSS+JS 的文件
有前面可以知道,我们可以给浏览器返回html + CSS +JS 格式的字符串,但是这种情况过于麻烦,因此, 可以直接返回一个html + CSS +JS的文件
from flask import Flask,render_template
app = Flask(__name__)
# http://127.0.0.1:9000/home
@app.route('/home')
def home():
#....
return render_template("home.html")
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9000)
二、HTML— 数据的展示
1. HTML----head 部分
- 在html中,文件的head部分通过一对
<head></head>
表示,内部可以设置标题,图标,关键字(例如:百度搜索时的输入)、描述语句(description,就是百度搜索后显示词条的内容描述)
<head> <meta charset="UTF-8"> <title>Title</title> </head>
- 示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>信息系统</title> <link rel="shortcut icon" href="/static/icon_2.png"> <meta name="keywords" content="CSDN博客,CSDN学院,CSDN论坛,CSDN直播"> <meta name="description" content="CSDN是全球知名中文IT技术交流平台."> </head> <body> <h1 style = "color:red;" onclick = 'alert(111)'>中国电信</h1> <h6>中国联通</h6> </body> </html>
2. 标题
- 1-6级标题
<body> <h1>一级标题</h1> <h2>二级标题</h2> <h3>三级标题</h3> <h4>四级标题</h4> <h5>五级标题</h5> <h6>六级标题</h6> </body>
3. HTML---- div/span
在HTML中,<div>
和 <span>
是两个常用的通用容器元素,用于组织和样式化内容。它们的主要区别在于默认显示方式和典型用途:
-
<div>
(块级容器)- 默认显示:块级元素
(独占一行,宽度默认100%)
。 - 用途:用于布局结构,分组大块内容(如页眉、侧边栏、卡片等)。
- 特点:
- 前后会自动换行。
- 通常搭配CSS设置宽度、边距、背景等样式。
- 可以嵌套其他块级或行内元素。
<div class="header"> <h1>标题</h1> <p>这是一个段落</p> </div>
- 默认显示:块级元素
-
<span>
(行内容器)- 默认显示:行内元素(不换行,宽度由内容决定)。
- 用途:包裹小段文本或行内元素,单独设置样式或脚本操作。
- 特点:
- 不会破坏文本流,适合标记部分文字(如高亮、图标等)。
- 不能直接设置宽度/高度(需通过
display: inline-block
等修改)。
<p>这是一段<span class="highlight">高亮</span>文本。</p>
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新闻咨询</title>
<link rel="shortcut icon" href="/static/icon_1.png">
</head>
<body>
<div>
<h1>日方称辽宁舰经过日南部岛屿前往西太平洋,外交部回应</h1>
<div>
<span style = "color:red;" >发布人</span>
<span>北京日报客户端</span>
<span style = "color:red;" >发布时间</span>
<span>2025-05-28 15:32</span>
</div>
<div>
<div>5月28日,外交部发言人毛宁主持例行记者会。</div>
<div>日本防卫省表示,辽宁舰航母经过日本南部岛屿并正在驶向太平洋的西部,日方正在密切监视这一举动。中方航母为何如此靠近日本?这是否在向日美以及台湾地区发出信号?</div>
<div>资料图“具体问题请你向中方的主管部门了解。”毛宁对此表示,“我可以告诉你的是,中国军舰在有关海域的活动完全符合国际法和国际惯例,希望日方客观理性看待。”</div>
</div>
</div>
</body>
</html>
注意:上面的模块中可以实现标签之间的嵌套
4. 模板渲染 —> 信息替换
在 Flask 中,模板渲染 是指将动态数据与预定义的 HTML 模板结合,生成最终的 HTML 页面并返回给用户的过程。
- Flask 应用代码 (
app.py
)from flask import Flask, render_template app = Flask(__name__) # http://127.0.0.1:9000/index @app.route("/index") def home(): # 1. 读取index.html文件里的内容 # 2. 渲染 == 替换 # 3. 将替换完的结果返回给用户浏览器 # 示例数据:列表、字典、嵌套字典 users = ["张三", "李四", "王五"] # 简单列表 infos = {"name":"朱十六","age":26,"city":"安徽"} user_info = { # 嵌套字典 "张三": {"age": 25, "job": "工程师", "skills": ["Python", "SQL"]}, "李四": {"age": 30, "job": "设计师", "skills": ["Photoshop", "UI/UX"]}, "王五": {"age": 22, "job": "学生", "skills": ["Java", "C++"]}, } posts = [ # 列表 + 字典混合 {"title": "Flask入门指南", "tags": ["Python", "Web"], "published": True}, {"title": "设计模式", "tags": ["编程", "OOP"], "published": False}, ] return render_template( "index.html", users=users, infos = infos , user_info=user_info, posts=posts, title="信息管理系统" ) if __name__ == "__main__": app.run(host='127.0.0.1', port=9000)
- 模板文件 (
templates/index.html
)<!DOCTYPE html> <html> <head> <title>{{ title }}</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } table { border-collapse: collapse; width: 50%; margin-bottom: 20px; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } .tag { background-color: #e0f7fa; padding: 2px 6px; border-radius: 3px; } .unpublished { color: #ff5722; font-style: italic; } </style> </head> <body> <h1>{{ title }}</h1> <!-- 1. 渲染简单列表方式一: --> <h2>用户列表</h2> <ul> <li>{{ users[0] }}</li> <li>{{ users[1] }}</li> <li>{{ users[2] }}</li> </ul> <!-- 1. 渲染简单列表方式二 --> <h2>用户列表</h2> <ul> {% for user in users %} <li>{{ user }}</li> {% endfor %} </ul> <!-- 2. 渲染简单字典方式一: --> <h2>用户列表</h2> <ul> <li>{{ infos.name }}</li> <li>{{ infos["age"] }}</li> <li>{{ infos["city"] }}</li> </ul> <h2>列表+字典嵌套</h2> </ul> <li>{{ posts[0].title }}</li> <li>{{ posts[0]["published"] }}</li> <li>{{ posts[0]["tags"][0] }}</li> <li>{{ posts[0]["tags"][1] }}</li> <li>{{ posts[1].title }}</li> <li>{{ posts[1]["published"] }}</li> <li>{{ posts[1]["tags"][0] }}</li> <li>{{ posts[1]["tags"][1] }}</li> </ul> <!-- 2. 渲染字典的键值对方式二: --> <h2>用户详细信息</h2> <table> <tr> <th>姓名</th> <th>年龄</th> <th>职业</th> <th>技能</th> </tr> {% for name, info in user_info.items() %} <tr> <td>{{ name }}</td> <td>{{ info.age }}</td> <td>{{ info.job }}</td> <td> {% for skill in info.skills %} <!-- 嵌套列表遍历,skill中是列表存储的 --> <span class="tag">{{ skill }}</span> {% endfor %} </td> </tr> {% endfor %} </table> <!-- 3. 条件判断 + 嵌套数据 --> <h2>文章列表</h2> {% for post in posts %} <!-- 列表中存储的是字典 --> <div {% if not post.published %}class="unpublished"{% endif %}> <h3>{{ post.title }}</h3> <p> 标签: {% for tag in post.tags %} <!-- tags 中存储的也是列表 --> <span class="tag">{{ tag }}</span> {% endfor %} {% if not post.published %} <em>(未发布)</em> {% endif %} </p> </div> {% endfor %} <!-- 4. 检查字典键是否存在 --> {% if "赵六" not in user_info %} <p style="color: #888;">注:赵六的信息未收录。</p> {% endif %} <!-- 5. 使用 loop.index 显示循环序号 --> <h2>带序号的用户列表</h2> <ol> {% for user in users %} <li>第{{ loop.index }}位:{{ user }}</li> {% endfor %} </ol> </body> </html>
注意: 渲染的时候一定要小心{% for post in posts %}
,{
和%
之间不要有空格,{
和%
之间同理,其他语句亦是如此
-
效果说明
-
关键语法总结
功能 | Jinja2 语法 | 示例场景 |
---|---|---|
遍历列表 | {% for item in list %} | 渲染用户列表 |
遍历字典键值 | {% for key, value in dict.items() %} | 渲染用户详情表 |
嵌套循环 | 多层 {% for %} | 渲染用户的技能标签 |
条件判断 | {% if condition %} | 检查文章是否发布 |
检查键是否存在 | {% if key in dict %} | 判断用户“赵六”是否存在 |
循环序号 | {{ loop.index }} | 显示“第1位:张三” |
若是代码中没有传入对应渲染的值,那么HTML页面则什么都不会显示
5. a标签
在HTML中,<a>
标签(锚标签,Anchor Tag)用于创建超链接,允许用户跳转到其他页面、文件、电子邮件地址或同一页面的特定位置。它是网页中实现导航和交互的核心元素之一。
- 基本语法
<a href="目标地址" 属性>链接文本或内容</a>
- 主要属性
-
href
(必需)- 定义链接的目标地址,可以是:
- 绝对URL:
<a href="https://www.example.com">示例</a>
- 相对路径:
<a href="/about.html">关于我们</a>
- 同一页面的锚点:
<a href="#section1">跳转到第一节</a>
- 电子邮件:
<a href="mailto:email@example.com">发送邮件</a>
- 电话:
<a href="tel:+123456789">拨打电话</a>
- 绝对URL:
- 定义链接的目标地址,可以是:
-
target
- 指定链接的打开方式:
_blank
:在新标签页打开。_self
(默认):在当前标签页打开。_parent
/_top
:在父框架或顶层窗口打开。
<a href="https://example.com" target="_blank">在新标签打开</a>
- 指定链接的打开方式:
-
rel
- 定义链接与当前页面的关系,常用于SEO和安全:
nofollow
:告诉搜索引擎不要追踪此链接。noopener noreferrer
:防止新页面通过window.opener
访问原页面(安全防护)。
<a href="https://external.com" rel="nofollow noopener noreferrer">外部链接</a>
- 定义链接与当前页面的关系,常用于SEO和安全:
-
download
- 提示浏览器下载链接的资源(而非打开):
<a href="/files/document.pdf" download>下载PDF</a>
-
title
- 鼠标悬停时显示的提示文本(辅助功能优化):
<a href="#faq" title="常见问题解答">FAQ</a>
-
- 常见用法示例
-
跳转到页面锚点
需在目标位置设置id
:<a href="#section2">跳转到第二节</a> <!-- 页面中的目标位置 --> <h2 id="section2">第二节标题</h2>
-
发送邮件
<a href="mailto:contact@example.com?subject=反馈&body=您好...">联系我们</a>
-
触发JavaScript
<a href="javascript:void(0);" onclick="alert('点击!')">点我</a>
-
- 注意事项
- 如果省略
href
,<a>
标签会变成普通的占位符(无链接功能)。 - 为提升可访问性,建议链接文本要有明确描述(避免“点击这里”)。
- 使用
target="_blank"
时,建议加上rel="noopener noreferrer"
以防止安全风险。
- 如果省略
完整示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<a href="https://www.baidu.com/" >访问baidu(不创建新的页面标签)</a>
</div>
<div>
<a href="https://www.baidu.com/" target="_blank" rel="noopener">访问baidu(打开新的页面)</a>
</div>
<div>
<a href="/news" target="_blank" rel="noopener">跳转至本地页面(简写)</a>
<a href="http://127.0.0.1:9000/news" target="_blank" rel="noopener">跳转至本地页面(完整)</a>
</div>
<div>
<!-- 跳转至 id="contact" 的目标出 -->
<!-- title="联系信息" 表示鼠标悬停在这里产生的提示信息 -->
<a href="#contact" title="联系信息">跳转到联系方式</a>
</div>
<div>
<a href="mailto:942898202@qq.com">发送邮件</a>
</div>
<div>
<a href="/files/document.pdf" download>下载PDF</a>
</div>
<div style="height: 5000px;"></div> <!-- 模拟长页面 -->
<h2 id="contact">17366020308</h2>
<p>邮箱:942898202@qq.com</p>
</body>
</html>
6. 插入图像
在HTML中,可以使用 <img>
标签 插入图片。这是一个 自闭合标签(不需要闭合标签),通过 src
属性指定图片路径,并可以设置宽度、高度、替代文本等属性。
- 基本语法
<img src="图片路径" alt="替代文本">
- 主要属性
属性 | 说明 | 示例 |
---|---|---|
src | 图片的URL或文件路径(必需) | src="images/photo.jpg" |
alt | 图片无法显示时的替代文本(SEO优化和可访问性) | alt="一只猫" |
width | 设置图片宽度(单位:像素或百分比) | width="300" 或 width="50%" |
height | 设置图片高度(单位:像素或百分比) | height="200" |
title | 鼠标悬停时显示的提示文本 | title="点击查看大图" |
loading | 控制图片懒加载(lazy 延迟加载) | loading="lazy" |
style | 内联CSS样式(如边框、边距等) | style="border: 1px solid #ccc;" |
示例代码
-
插入本地图片
<img src="images/cat.jpg" alt="一只橘猫" width="300" height="200">
- 图片路径可以是:
- 相对路径(相对于当前HTML文件):
src="images/cat.jpg"
- 绝对路径(完整URL):
src="https://example.com/images/cat.jpg"
- 相对路径(相对于当前HTML文件):
- 图片路径可以是:
-
插入网络图片
<img src="https://example.com/pic.jpg" alt="网络图片" width="400">
-
带链接的图片
用<a>
标签包裹<img>
,使图片可点击跳转:<a href="https://example.com" target="_blank"> <img src="logo.png" alt="公司Logo"> </a>
-
响应式图片(自适应宽度)
<img src="photo.jpg" alt="风景照" style="max-width: 100%; height: auto;">
max-width: 100%
确保图片不超过容器宽度height: auto
保持比例不变
-
懒加载(Lazy Loading)
延迟加载图片,提升页面性能:<img src="large-image.jpg" alt="大图" loading="lazy">
完整HTML示例
<!DOCTYPE html>
<html>
<head>
<title>插入图片示例</title>
</head>
<body>
<h1>我的相册</h1>
<!-- 本地图片 -->
<img src="images/sunset.jpg" alt="日落" width="500">
<!-- 网络图片 -->
<img src="https://picsum.photos/600/400" alt="随机图片" loading="lazy">
<!-- 可点击的图片 -->
<a href="https://example.com">
<img src="logo.png" alt="网站Logo" title="点击访问">
</a>
<a href="https://portal.irayple.com/Home" title="跳转至主页" target="_blank">
<img src="static/1.jpeg" alt="风景照" style="max-width: 30%; height: auto;">
</a>
</body>
</html>
通过 <img>
标签,你可以轻松地在网页中嵌入图片,并控制其显示方式!
7. 列表
在HTML中,列表主要有三种类型:无序列表、有序列表和定义列表。以下是它们的语法和示例:
- 关于这里的便签记忆:
- 无序列表:
<ul>
标签表示(ul
是unordered list
的缩写),元素标签用<li>
,代表list
- 有序列表:
<ol>
标签表示(ol
是ordered list
的缩写),元素标签用<li>
,代表list
- 定义列表:
<dl>
标签表示(dl
是define list
的缩写)
- 无序列表:
- 无序列表(
<ul>
)
用于展示没有特定顺序的项目,默认用实心圆点(•
)标记。<ul> <li>项目一</li> <li>项目二</li> <li>项目三</li> </ul>
效果:
属性:
- 通过CSS的
list-style-type
可以修改标记样式(如circle
、square
、none
)。
- 有序列表(
<ol>
)
用于需要顺序的项目,默认用数字标记。<ol> <li>第一步</li> <li>第二步</li> <li>第三步</li> </ol>
效果:
属性:
type
:可指定标记类型(如1
、A
、a
、I
、i
)。start
:设置起始编号(如start="3"
从3开始)。reversed
:倒序排列(HTML5新增)。
示例:
<ol type="A" start="2">
<li>项目B</li>
<li>项目C</li>
</ol>
- 定义列表(
<dl>
)
用于术语及其定义的组合,如字典。<dl> <dt>HTML</dt> <dd>超文本标记语言,用于网页结构。</dd> <dt>CSS</dt> <dd>层叠样式表,用于网页样式设计。</dd> </dl>
效果:
- 嵌套列表
列表可以多层嵌套,例如:<ul> <li>水果 <ul> <li>苹果</li> <li>香蕉</li> </ul> </li> <li>蔬菜 <ol> <li>番茄</li> <li>豌豆</li> </ol> </li> </ul>
效果:
8. 表格
在 HTML 中,表格使用 <table>
标签定义,由行(<tr>
— table row
)、表头(<th>
— table head
)和单元格(<td>
— Table Data Cell
)组成。以下是详细语法和示例:
- 基本表格结构
<table> <tr> <th>表头1</th> <th>表头2</th> </tr> <tr> <td>数据1</td> <td>数据2</td> </tr> </table>
效果:
- 表格关键标签
标签 | 说明 |
---|---|
<table> | 定义整个表格 |
<tr> | 定义一行(table row) |
<th> | 定义表头单元格(加粗居中) |
<td> | 定义普通单元格(table data) |
<caption> | 表格标题(显示在表格上方) |
- 合并单元格
-
跨列合并(
colspan
)
合并同一行中的多个单元格:<td colspan="2">合并两列</td>
-
跨行合并(
rowspan
)
合并同一列中的多个单元格:<td rowspan="2">合并两行</td>
示例:
<table border="1">
<tr>
<th>姓名</th>
<th colspan="2">联系方式</th>
</tr>
<tr>
<td></td>
<td>电话</td>
<td>邮箱</td>
</tr>
<tr>
<td>张三</td>
<td>3698</td>
<td>c@example.com</td>
</tr>
<tr>
<td rowspan="2">李四</td>
<td>123</td>
<td>a@example.com</td>
</tr>
<tr>
<td>456</td>
<td>b@example.com</td>
</tr>
</table>
效果:
- 表格分组(语义化结构)
标签 | 说明 |
---|---|
<thead> | 表头区域(可选) |
<tbody> | 表格主体(必须) |
<tfoot> | 表尾区域(可选) |
示例:
<table border="1">
<thead>
<tr><th>月份</th><th>收入</th></tr>
</thead>
<tbody>
<tr><td>1月</td><td>1000</td></tr>
<tr><td>2月</td><td>1500</td></tr>
</tbody>
<tfoot>
<tr><td>总计</td><td>2500</td></tr>
</tfoot>
</table>
- 常用属性(已废弃,建议用CSS替代)
属性 | 说明 | 替代CSS |
---|---|---|
border | 边框粗细 | border: 1px solid; |
cellspacing | 单元格间距 | border-spacing: 5px; |
cellpadding | 单元格内边距 | padding: 10px; |
width | 表格宽度 | width: 100%; |
示例:
<table style="border: 1px solid; width: 100%;">
<tr><td>用CSS控制样式</td></tr>
</table>
- 响应式表格
为小屏幕设备添加横向滚动:
<div style="overflow-x: auto;">
<table>
<!-- 宽表格内容 -->
</table>
</div>
示例程序1:
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>图片</th>
<th>标题</th>
<th>价格</th>
<th>链接</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src="static/icon_1.jpg" style="width:80px"></td>
<td>选择正确</td>
<td>1999</td>
<td><a href="https://portal.irayple.com/Home" target="_blank">跳转</a></td>
</tr>
<tr>
<td>2</td>
<td><img src="static/1.jpeg" style="width:80px"></td>
<td>选择正确</td>
<td>4999</td>
<td><a href="https://portal.irayple.com/Home" target="_blank">跳转</a></td>
</tr>
</tbody>
<tfoot>
<td>小节</td>
<td><img src="static/1.jpeg" style="width:80px"></td>
<td>choice</td>
<td>618活动</td>
<td><a href="https://portal.irayple.com/Home" target="_blank">跳转</a></td>
</tfoot>
</table>
示例程序2:结合模板渲染
Python代码:
# http://127.0.0.1:9000/goods
@app.route("/goods")
def goods():
data_list=[
{"id":1,"img_url":"static/mobile/15sp.png","title":"小米15spro","price":5499,
"url":"https://www.mi.com/shop/buy/detail?product_id=21305/"},
{"id": 2, "img_url": "static/mobile/civ5pro.png", "title": "小米civ5pro", "price": 2799,
"url": "https://www.mi.com/shop/buy/detail?product_id=21298/"},
{"id": 2, "img_url": "static/mobile/15u.jpg", "title": "小米15Ultra", "price": 6499,
"url": "https://www.mi.com/shop/buy/detail?product_id=20982/"},
]
return render_template(
"goods.html",
data_list = data_list
)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9000)
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>图片</th>
<th>标题</th>
<th>价格</th>
<th>链接</th>
</tr>
</thead>
<tbody>
{% for item in data_list %}
<tr>
<td>{{item.id}}</td>
<td><img src="{{item.img_url}}" style="width:80px"></td>
<td>{{item.title}}</td>
<td>{{item.price}}</td>
<td><a href="{{item.url}}" target="_blank">点击跳转</a></td>
</tr>
{% endfor %}
</tbody>
</table>
三、HTML— 用户输入
1. input 系列
HTML的<input>
元素用于创建交互式控件,以便用户输入数据。以下是<input>
元素的基本语法和常见属性:
基本语法
<input type="input_type" name="field_name" id="field_id" value="default_value">
主要属性
-
type - 指定输入类型(必需):
text
- 单行文本输入框(默认值)password
- 密码输入框(内容显示为圆点)email
- 电子邮件输入框number
- 数字输入框date
- 日期选择器checkbox
- 复选框radio
- 单选按钮file
- 文件上传submit
- 提交按钮reset
- 重置按钮button
- 普通按钮hidden
- 隐藏字段- 等等(共有20多种类型)
-
name - 字段名称(表单提交时使用)
-
表单提交时的参数名:
- 当表单提交时,浏览器会以
name=value
的形式将数据发送到服务器- 例如:
<input type="text" name="username" value="John">
提交后会生成username=John
- 例如:
- 当表单提交时,浏览器会以
-
表单分组:
- 对于单选按钮(radio),相同
name
的按钮属于同一组,只能选择其中一个,最后也是以name=value
的形式将数据发送到服务器,但是这个name=value
中的value就是选项标签中的value属性的值。(如:male
或者female
)<input type="radio" name="gender" value="male"> 男 <input type="radio" name="gender" value="female"> 女
- 对于单选按钮(radio),相同
-
-
id - 唯一标识符(用于CSS和JavaScript)
-
value - 默认值
-
placeholder - 提示文本(当输入框为空时显示)
-
required - 必填字段(布尔属性):在 HTML 表单中,
required
属性用于指定某个表单字段(如<input>
、<select>
或<textarea>
)必须在提交表单之前填写或选择。它是一个布尔属性,添加后表示该字段是必填项。示例
-
文本输入框必填
<input type="text" name="username" required>
- 如果用户未填写,提交时会提示“请填写此字段”。
-
单选按钮必选
<input type="radio" name="gender" value="male" required> 男 <input type="radio" name="gender" value="female"> 女
- 必须选择其中一个选项,否则无法提交。
-
下拉选择框必选
<select name="country" required> <option value="">请选择国家</option> <option value="cn">中国</option> <option value="us">美国</option> </select>
- 必须选择一个非空值(
value=""
的选项会被视为未选择)。
- 必须选择一个非空值(
-
复选框必选(至少选一个)
<input type="checkbox" name="hobby" value="sports" required> 运动 <input type="checkbox" name="hobby" value="music"> 音乐
- 如果
required
放在单个复选框上,表示必须勾选它:<input type="checkbox" name="agree" required> 我同意协议
- 如果
-
-
disabled - 禁用输入字段(布尔属性)
-
readonly - 只读(布尔属性)
-
maxlength - 最大字符数
-
min/max - 数值/日期的最小/最大值(适用于number/date类型)
-
step - 数值的增量(适用于number类型)
-
checked - 默认选中(适用于checkbox和radio)
-
multiple - 允许多个值(适用于file和email类型)
示例代码
<!-- 文本输入框 -->
<input type="text" name="username" id="username" placeholder="请输入用户名">
<!-- 密码输入框 -->
<input type="password" name="password" id="password">
<!-- 单选按钮 -->
<input type="radio" name="gender" id="male" value="male" checked>
<input type="radio" name="gender" id="female" value="female">
<!-- 复选框 -->
<input type="checkbox" name="hobby" id="reading" value="reading">
<input type="checkbox" name="hobby" id="sports" value="sports">
<!-- 数字输入 -->
<input type="number" name="age" id="age" min="18" max="99">
<!-- 日期选择 -->
<input type="date" name="birthday" id="birthday">
<!-- 文件上传 -->
<input type="file" name="avatar" id="avatar" multiple>
<!-- 提交按钮 -->
<input type="submit" value="提交表单">
<input>
元素通常嵌套在<form>
元素中使用,但也可以单独使用。
完整示例
<h2>用户登录</h2>
<div>
<!-- 文本输入 -->
<span>用户名:</span>
<input type = "text" name = "user_name" placeholder="用户名"/>
</div>
<div>
<!-- 密码输入隐藏输入 -->
<span>密 码:</span>
<input type="password" name="password" id="password"/>
</div>
<div>
<!-- 按钮——登录为vlue -->
<input type="button" value="登录"/>
</div>
<div>
<!-- 单选框 -->
<span>性别:</span>
<input type="radio" name="gender" id="male" value="male" checked>男</input>
<input type="radio" name="gender" id="female" value="female">女</input>
<input type="radio" name="gender" id="unknown" value="unknown">未知</input>
</div>
<div>
<!-- 复选框 -->
<span>爱好:</span>
<input type="checkbox" name="hobby" id="reading" value="reading">阅读</input>
<input type="checkbox" name="hobby" id="sports" value="sports">运动</input>
<input type="checkbox" name="hobby" id="music" value="music">音乐</input>
</div>
<div>
<!-- 数字输入 -->
<span>数字输入:</span>
<input type="number" name="age" id="age" min="18" max="99">
</div>
<div>
<!-- 日期选择 -->
<span>日期选择:</span>
<input type="date" name="birthday" id="birthday">
</div>
<div>
<!-- 文件上传 -->
<span>文件上传:</span>
<input type="file" name="avatar" id="avatar" multiple>
</div>
2. 下拉框
-
基本结构
<select name="下拉框名称" id="唯一标识符"> <option value="选项值">显示文本</option> <option value="option2">选项2</option> </select>
-
<select>
核心属性属性 说明 示例 name
表单提交时的字段名 name="country"
id
唯一标识符 id="country-select"
multiple
允许多选 <select multiple>
size
可见选项行数 size="4"
disabled
禁用下拉框 <select disabled>
required
必填字段 <select required>
form
关联的表单ID form="form1"
autofocus
自动获取焦点 <select autofocus>
-
<option>
核心属性属性 说明 示例 value
表单提交的值 value="us"
selected
默认选中 <option selected>
disabled
禁用选项 <option disabled>
label
替代显示文本 label="United States"
-
<optgroup>
分组属性属性 说明 示例 label
分组标题 label="亚洲国家"
disabled
禁用整个分组 <optgroup disabled>
-
完整示例
<form id="user-form"> <!-- 基本下拉框 --> <!--br表示换行标签--> <label for="gender">性别:</label><br> <select id="gender" name="gender" required> <option value="">-- 请选择 --</option> <option value="male">男</option> <option value="female">女</option> </select> <!--br表示换行标签--> <br><br><br><br><br><br> <!-- 分组下拉框 --> <label for="country">国家/地区:</label><br> <select id="country" name="country" style="width: 200px;height:50px"> <optgroup label="亚洲"> <option value="cn">中国</option> <option value="jp">日本</option> </optgroup> <optgroup label="欧洲"> <option value="uk">英国</option> <option value="fr">法国</option> </optgroup> </select> <!--br表示换行标签--> <br><br><br><br><br><br><br><br><br> <!-- 多选下拉框 --> <label for="hobbies">兴趣爱好:</label><br> <select id="hobbies" name="hobbies" multiple size="4" style="width: 200px"> <option value="sports">运动</option> <option value="music">音乐</option> <option value="reading" selected>阅读</option> <option value="travel">旅行</option> </select><br> <input type="submit" value="提交"> </form>
-
使用注意
- 默认选项:建议第一个选项作为提示项,设置
value=""
和required
属性 - 多选操作:
- Windows: Ctrl + 点击
- Mac: Command + 点击
- 连续选择: Shift + 点击
- 样式限制:原生下拉框样式有限,复杂需求建议使用JavaScript库
- 表单关联:当
<select>
不在<form>
内时,使用form="form-id"
属性关联
- 默认选项:建议第一个选项作为提示项,设置
-
注意事项
value
属性是表单提交时发送到服务器的值- 未设置
value
属性时,提交的是选项的文本内容 multiple
和size
属性通常配合使用- 移动设备上下拉框的表现可能与桌面端不同
3. 多行文本
<!-- 基本结构 -->
<textarea
id="myTextarea" <!-- 元素ID -->
name="userContent" <!-- 表单字段名 -->
rows="5" <!-- 可见行数 -->
cols="40" <!-- 可见宽度(字符数) -->
maxlength="500" <!-- 最大字符数 -->
placeholder="请输入..." <!-- 提示文本 -->
required <!-- 必填字段 -->
readonly <!-- 只读(可选) -->
disabled <!-- 禁用(可选) -->
autofocus <!-- 自动聚焦(可选) -->
wrap="hard" <!-- 换行方式(soft/hard/off) -->
style="width:300px; height:150px; resize:none;"> <!-- CSS样式 -->
默认文本内容
</textarea>
完整示例:
<!-- 实际应用示例 -->
<form>
<label for="comment">评论:</label><br>
<textarea id="comment" name="comment" rows="4"
placeholder="请留下您的评论..." required
maxlength="500"></textarea><br>
<button type="submit">提交</button>
</form>
<br><br><br><br>
<form>
<label for="comment">批注</label><br>
<textarea id="remark" name="remark" style="width:400px;height:100px"
placeholder="请留下您的批注..." required
maxlength="500"></textarea><br>
<button type="submit">提交</button>
</form>
关键点说明:
- 内容写在开始和结束标签之间,不是通过
value
属性 - 现代开发推荐用CSS的
width/height
替代rows/cols
resize:none
可禁止用户调整大小- 通过
maxlength
限制输入长度 required
属性确保表单提交前必须填写
4. label标签
<label>
是HTML中用于关联表单控件(如<input>
、<select>
、<textarea>
等)的重要标签,在CSS中可以通过多种方式对其进行样式设置。以下是关于<label>
标签的详细说明:
基本功能
-
关联表单控件:
- 通过
for
属性与表单控件的id
关联
<label for="username">用户名:</label> <input type="text" id="username">
- 通过
-
提升可用性:
- 点击
<label>
会自动聚焦关联的表单控件 - 对屏幕阅读器等辅助技术更友好
- 点击
5. Form 标签
Form标签是前面标签的上级 + submit就能提交数据
<form action="要提交的地址" method="get/post">
<input type="text" />
<input type="password" />
<input type="submit" value="提交" />
</form>
<form>
<input type="text" />
<input type="password" />
<input type="submit" value="提交" />
</form>
。。。。
四、get和post请求
案例1:用户登录—get请求
python代码
from flask import Flask,render_template,request
app = Flask(__name__)
# http://127.0.0.1:9000/login
@app.route('/login')
def login():
#....
return render_template("login.html")
# 登录信息的表单提交之后跳转的网址以及内部函数
# http://127.0.0.1:9000/goin
@app.route('/goin')
def goin():
#....
print(request.args)
# 获取浏览器发送过来的数据参数,通过字典的方式获取
username = request.args.get("username")
password = request.args.get("password")
print("uesrname:{} — password:{}".format(username,password))
return "ok"
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9000)
<!--表单提交后跳转的网址http://127.0.0.1:9000/goin -->
<form action="http://127.0.0.1:9000/goin" method="get">
<h2>用户登录</h2>
<div>
<!-- 文本输入 -->
<span>用户名:</span>
<input type = "text" name = "username" placeholder="用户名"/>
</div>
<div>
<!-- 密码输入隐藏输入 -->
<span>密 码:</span>
<input type="password" name="password" id="password"/>
</div>
<div>
<!-- 按钮——登录为vlue -->
<input type="submit" value="登录"/>
</div>
</form>
默认是get
请求,所以url中显示了输入的用户名和密码
案例2:用户登录—post请求
from flask import Flask,render_template,request
app = Flask(__name__)
# http://127.0.0.1:9000/login
@app.route('/login')
def login():
#....
return render_template("login.html")
# 登录信息的表单提交之后跳转的网址以及内部函数
# 这里设置post请求
# http://127.0.0.1:9000/goin
@app.route('/goin',methods=["post"])
def goin():
#....
print(request.args)
# 获取浏览器发送过来的数据参数,通过字典的方式获取
username = request.form.get("username")
password = request.form.get("password")
print("uesrname:{} — password:{}".format(username,password))
return "ok"
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9000)
<!--表单提交后跳转的网址http://127.0.0.1:9000/goin -->
<!--这里设置post请求 -->
<form action="http://127.0.0.1:9000/goin" method="post">
<h2>用户登录</h2>
<div>
<!-- 文本输入 -->
<span>用户名:</span>
<input type = "text" name = "username" placeholder="用户名"/>
</div>
<div>
<!-- 密码输入隐藏输入 -->
<span>密 码:</span>
<input type="password" name="password" id="password"/>
</div>
<div>
<!-- 按钮——登录为vlue -->
<input type="submit" value="登录"/>
</div>
</form>
由于是post
请求,点击登录之后的url中就不显示刚刚填写的登录信息
post请求和get请求的区别
当然!我们用更直白的语言和比喻来解释 GET 和 POST 的区别,结合生活中的例子,保证你一听就懂。
(1). 核心区别一句话总结
- GET:像查字典——你告诉服务器“我要什么”,服务器返回数据(只读操作)。
- POST:像填表格——你提交数据给服务器,让它去处理(写入操作)。
(2). 具体对比(用快递举例)
对比项 | GET(查快递) | POST(寄快递) |
---|---|---|
用途 | 从服务器“拿”数据(比如查订单、搜商品) | 向服务器“发”数据(比如登录、下单) |
数据位置 | 数据挂在URL上(像快递单号暴露在快递盒外面) | 数据藏在包裹里(像快递内容在盒子内部) |
安全性 | 不安全(URL能被看到、被缓存) | 相对安全(数据不直接暴露,但也要加密) |
数据量 | 限制大(URL长度有限,比如最多2048字符) | 无限制(能发大文件、长文本) |
浏览器行为 | 能收藏、能刷新、能分享链接 | 不能直接收藏或刷新(可能重复提交) |
(3). 举个实际例子
场景:用户登录
-
如果用GET(错误示范❌):
- URL长这样:
https://example.com/login?username=admin&password=123456
- 问题:密码直接暴露在地址栏!别人看浏览器历史就能盗号。
- URL长这样:
-
如果用POST(正确做法✅):
- URL不变:
https://example.com/login
- 密码藏在请求体里,肉眼不可见,相对安全。
- URL不变:
(4). Flask代码对比
from flask import Flask, request
app = Flask(__name__)
# GET请求:通过URL传参(比如搜索)
@app.route('/search', methods=['GET'])
def search():
keyword = request.args.get('q') # 从URL获取参数,如 /search?q=apple
return f"你搜索了: {keyword}"
# POST请求:通过表单提交数据(比如登录)
@app.route('/login', methods=['POST'])
def login():
username = request.form.get('username') # 从表单获取数据
password = request.form.get('password')
return f"用户名: {username}, 密码已隐藏"
(5). 什么时候用哪个?
-
用GET:
- 你不修改服务器数据,只是“看看”(比如:加载网页、搜索、查看详情)。
- 记住:GET请求可以被用户手动刷新、分享链接,不会出问题。
-
用POST:
- 你要修改服务器数据(比如:登录、注册、付款、删除内容)。
- 记住:POST请求如果刷新浏览器,可能会弹窗提示“是否重新提交表单”。
说明:关于get/post请求
- GET请求
网址输入+回车访问 ——> GET
连接点过去 ——> GET
点击按钮+URL中 ?n1=123&n2=xxx ——> GET
- POST
<form action="????" method = "post">
...
</form>
提交后,再URL中没有看到参数 ——> post
如果它的请求都是在干同一件事,一般会选择用 一个url+多个请求的方式进行区分。
例如:登录/注册
- 第一步:访问页面,看到输入页面 GET
http://127.0.0.1:9000/login
@app.route('/login',methods=['GET','POST']) def login(): if request.method == "GET": return render_template("login.html")
- 第二步:用户看到页面+用户输入+点击按钮提交 —— HTML
<form action="http://127.0.0.1:9000/login" method="post"> <h2>用户登录</h2> <div> <!-- 文本输入 --> <span>用户名:</span> <input type = "text" name = "username" placeholder="用户名"/> </div> <div> <!-- 密码输入隐藏输入 --> <span>密 码:</span> <input type="password" name="password" id="password"/> </div> <div> <!-- 按钮——登录为vlue --> <input type="submit" value="登录"/> </div> </form>
- 第三步:接受POST提交的数据
# http://127.0.0.1:9000/login @app.route('/login',methods=['GET','POST']) def login(): if request.method == "GET": return render_template("login.html") username = request.form.get("username") password = request.form.get("password") print("uesrname:{} — password:{}".format(username,password)) return "ok"
案例3:用户登录 get+post
from flask import Flask,render_template,request,redirect
app = Flask(__name__)
# http://127.0.0.1:9000/login
# 即接受post请求,也接受get请求
@app.route('/login',methods=['GET','POST'])
def login():
# 若是get请求(输入网址+回车),那么返回登陆的html页面
if request.method == "GET":
return render_template("login.html")
username = request.form.get("username")
password = request.form.get("password")
print("uesrname:{} — password:{}".format(username,password))
if username == "root" and password == "123":
#登录成功,跳转到另外一个页面
return redirect("http://www.baidu.com")
else:
return render_template("login.html",message="登录失败")
if __name__ == '__main__':
app.run(host='127.0.0.1', port=9000)
<form action="http://127.0.0.1:9000/login" method="post">
<h2>用户登录</h2>
<div>
<!-- 文本输入 -->
<span>用户名:</span>
<input type = "text" name = "username" placeholder="用户名"/>
</div>
<div>
<!-- 密码输入隐藏输入 -->
<span>密 码:</span>
<input type="password" name="password" id="password"/>
</div>
<div>
<!-- 按钮——登录为vlue -->
<input type="submit" value="登录"/>
<span style="color: #ff5722">{{message}}</span>
</div>
</form>
- 若登录成功,直接跳转到新的页面
注意事项:
-
若是密码输入成功则会进行跳转,失败则返回登录界面,但是会有提示信息"登录失败"
if username == "root" and password == "123": #登录成功,跳转到另外一个页面 return redirect("http://www.baidu.com") else: return render_template("login.html",message="登录失败")
- 这里登录成功界面跳转,用到了
redirect
方法; - 登录失败还是返回
login.html
模板,但是此时有文字渲染。(当返回输入参数message的时候,模板进行渲染替换文字,但是若不传入message参数,就部进行替换,显示为空的)
- 这里登录成功界面跳转,用到了
-
HTML
中的关于网址,之前有几个标签会进行链接如:<a href= "???">百度</a> <img src = "???"/> <form action="????"></form>
- 若是跳转到外部的其他网站,则要写出全名
<a href= "https://www.baidu.com">百度</a> <img src = "https://www.baidu.com"/> <form action="https://www.baidu.com"></form>
- 若是跳转到自己的内部网站,可以省略前面的
http://127.0.0.1:9000
可以简写成<a href= "http://127.0.0.1:9000/admin">百度</a> <img src = "http://127.0.0.1:9000/static/mobile/15sp.png"/> <form action="http://127.0.0.1:9000/login"></form>
<a href= "/admin">百度</a> <img src = "/static/mobile/15sp.png"/> <form action="/login"></form>
- 若是跳转到外部的其他网站,则要写出全名
五、综合案例(登录+注册)
-
输入登录网址,进入登录界面
-
若有账号,则进行登录操作
- 登录成功——显示已经注册的用户信息,并以列表的形式呈现
- 登录失败——则依旧停留在登录界面,只不过界面显示登录失败
-
若不存在账号,则进行注册操作,点击注册按钮,跳转至注册界面
-
Python代码
from flask import Flask,render_template,request,redirect app = Flask(__name__) # 注册函数 # 登录,设置请求时post+get @app.route('/register',methods=['GET','POST']) def register(): if request.method == 'GET': return render_template("register.html") print(request.form) username = request.form['username'] password = request.form['password'] gender = request.form['gender'] hobby = request.form.getlist('hobby') city = request.form.get('city') more = request.form.get('more') print( username, password, gender, hobby, city,more) #将用户信息写入txt文件 with open("db.txt",mode="a",encoding="utf-8") as f: f.write(f"{username},{password},{gender},{'_'.join(hobby)},{city},{more}\n") #注册成功返回至登录界面 return redirect("/login") # return render_template("register.html",message = "注册成功") # 登录成功之后,显示的界面(以表格的形式显示用户信息) # 这里设置为get请求,因为这里实际上是点击按钮,或者网址输入+回车过去,这个就是get请求 @app.route('/usr/list',methods=['GET']) def usr_list(): #通过字典,创建映射关系,因为按钮、下拉框的值直观呈现的效果不好,这里进行二次处理 gender_map = { "male":"男", "female":"女", } city_map = { "bj":"北京", "sh":"上海", "nj":"南京", "hz":"杭州", } hobby_map = { "20":"篮球", "30":"足球", "40":"乒乓球", } data_list = [] # 打开文件,逐行读取内容 with open("db.txt",mode="r",encoding="utf-8") as f: for line in f: # 去除字符串 line 首尾的空白字符 line = line.strip() if not line: continue # 一行的信息是以","区分的,所以通过,将信息分割开,并赋值给对应的变量 user,pwd,gender,hobby,city,more = line.split(',') # gender、city变量获取的值是缩写,这里通过前面字典的映射关系变成中文 gender_text= gender_map[gender] city_text= city_map[city] # hobby是一些以"_"分割开的字符串,这里分割开,并且以列表的形式赋值给hobby_list hobby_list = hobby.split('_') hobby_text_list = [] # hobby_list 里的值过前面字典的映射关系变成中文,并且添加到新的列表hobby_text_list 中 for item in hobby_list: hobby_text_list.append(hobby_map[item]) hobby_string = "、".join(hobby_text_list) data_list.append({ "user":user, "pwd":pwd, "gender":gender_text, "hobby":hobby_string, "city":city_text, "more":more, }) print(user,pwd,gender_text,hobby_string,city_text,more) # 返回HTML模板,并且进行渲染 return render_template("user_list.html",data_list=data_list) # 登录,设置请求时post+get @app.route("/login",methods=['GET','POST']) def login(): if request.method == 'GET': return render_template("login.html") username = request.form['username'] password = request.form['password'] is_success = False with open("db.txt",mode="r",encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue db_user,db_pwd,*v3 = line.split(',') if db_user == username and db_pwd == password: is_success = True break if is_success: #登录成功,返回用户列表 return redirect("/usr/list") else: #登录失败 return render_template("login.html",message = "用户名或密码错误") if __name__ == '__main__': app.run(host='127.0.0.1', port=5000)
-
登录的HTML界面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户登录</title> </head> <body> <h2>用户登录</h2> <form action="/login" method="post"> <input type="text" name = "username" placeholder="用户名" required> <input type="password" name="password" placeholder="密码" required> <input type="submit" value="登录"> <span style="color: greenyellow">{{ message }}</span> <br> <a href="/register">注册</a> </form> </body> </html>
-
登陆成功后,跳转的用户信息表格显示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户信息</title> </head> <body> <h1>用户信息列表</h1> <table border="1"> <thead> <tr> <th>用户名</th> <th>密码</th> <th>性别</th> <th>爱好</th> <th>城市</th> <th>其他</th> </tr> </thead> <tbody> {% for row in data_list %} <tr> <td>{{ row.user }}</td> <td>{{ row.pwd }}</td> <td>{{ row.gender }}</td> <td>{{ row.hobby }}</td> <td>{{ row.city }}</td> <td>{{ row.more }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
-
用户注册界面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册</title> </head> <body> <h2>用户注册</h2> <form action="/register" method="post"> <div> <!-- label 标签 点击后,可以选中对应的 id 所在的 input ,属性for后面跟的是input中的id内容 --> <label for="username">用户名</label> <input id="username" type="text" placeholder="请输入用户名:" name="username" required> </div> <div> <!-- label 标签 点击后,可以选中对应的 id 所在的 input ,属性for后面跟的是input中的id内容 --> <label for="password">密码</label> <input id="password" type="password" placeholder="请输入密码" name="password" required> </div> <div> <label>性别</label> <!--对于这种选择框,提交后台后,是将value的值传递给后台的 --> <input type="radio" name="gender" value="male"> 男 <input type="radio" name="gender" value="female"> 女 </div> <div> <label>爱好</label> <!--对于这种选择框,提交后台后,是将value的值传递给后台的 --> <input type="checkbox" name="hobby" value="20"> 篮球 <input type="checkbox" name="hobby" value="30"> 足球 <input type="checkbox" name="hobby" value="40"> 乒乓球 </div> <div> <label>城市</label> <select name = "city"> <option value="bj">北京</option> <option value="sh">上海</option> <option value="nj">南京</option> <option value="hz">杭州</option> </select> </div> <div> <label>备注信息</label> <textarea name = "more" style="width: 500px;height: 100px"></textarea> </div> <input type="submit" value="注册"> <span style="color: red">{{ message }}</span> </form> </body> </html>
注册完之后就会返回登录界面重新输入用户民和密码
登录成功显示用户信息表格