文章目录
- 一、Flask 简介
- 1.1 安装虚拟环境
- 1.1.1 安装Virtualenv
- 1.1.2 创建虚拟环境
- 1.1.3 激活虚拟环境
- 1.2 安装Flask
- 1.3 第一个Flask
- 二、Flask基础
- 2.1 开启调试模式
- 2.2 路由
- 2.2.1 变量规则
- 2.2.2 构造URL
- 2.2.3 HTTP方法
- 2.3 静态文件
- 2.4 蓝图
- 三、模板
- 3.1 渲染模板
- 3.2 变量
- 3.3 控制结构
- 3.3.1 条件控制语句
- 3.3.2 循环语句
- 3.3.3 宏
- 3.3.4 公共代码
- 四、Web表单
- 4.1 安装
- 4.2 CSRF的保护和验证
- 4.3 表单类
- 4.4 把表单渲染成HTML
一、Flask 简介
Flask 依赖两个外部库:WerkZeug 和 Jinja2。WerkZeug 是一个WSGI(在web应用和多种服务器之间的标准Python 接口)工具集。Jinja2负责渲染模板。所以在安装Flask之前,需要安装这两个外部库,而最简单的方法就是使用 Virtualenv 创建虚拟环境
1.1 安装虚拟环境
1.1.1 安装Virtualenv
pip install virtualenv
检验
virtualenv
--version
1.1.2 创建虚拟环境
下一步就是使用Virtualenv 命令在当前文件夹创建Python虚拟环境。创建虚拟环境之后当前文件夹会出现一个子文件夹,名字就是下述命令中指定的参数
virtualenv venv


1.1.3 激活虚拟环境
venv\Scripts\activate
1.2 安装Flask
pip install flask
安装校验
pip
list --format columns

1.3 第一个Flask
from flask
import Flask
app
= Flask
(__name__
)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__
== '__main__':
app
.run
(debug
=True)

(1)首先我们导入了Flask类。这个类的实例将会是我们的WSGI应用程序
(2)接下来,我们创建了一个该类的实例,第一个参数是应用模块或者包名的名称。如果你还用单一的模块,比如本例,你应该使用__name__,因为模块的名称将会因其作为一个单独的应用模块启动还是作为模块导入而有不同(也是__main_或者实际的导入名)。这是必须得,这样Flask才知道到哪儿去模板,静态文件等。详情见Flask的文档。
(3)然后,我们使用route()装饰器告诉Flask什么样的URL能触发我们的函数
(4)这个函数的名字也在生成URL时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息
(5)最后我们使用run()函数来让应用运行在本地的服务器上面。其中if__name __=='__main__':确保服务器只会在该脚本被Python解释器直接执行的时候才会运行,而不是作为模板导入的时候
二、Flask基础
2.1 开启调试模式
虽然run()方法使用与启动本地的开发服务,但是用户没每次修改代码后需要手动的重启服务,这样并不优雅,而Flask可以做到更好。如果你启用了调试支持,服务器会在代码修改后自动重新载入,并且在发生错误的时候提供一个相当可用的调试器 相当于Java的热部署
使用方法,直接在代码中添加
app
.run
(debug
=True)
或者
app
.debug
=True
app
.run
()
2.2 路由
处理URL和函数之间的关系的程序称之为路由
@app.route('/')
def hello_world():
return 'Hello World!
'

修饰器是Python语言的标准特性,可以使用不同的方法修改函数的行为。惯常用法是使用修饰器把函数注册为事件的处理程序
2.2.1 变量规则
要给URL添加变量部分,你可以把这些特殊的字段编辑为,这个部分将会作为命名参数传递到你的函数。规格可以使用converter:variable_name指定一个可选的转化器
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/user/
')
def show_user_profile(username):
# 显示该用户名的用户信息
return 'User %s' % username
@app.route('/post/')
def show_post(post_id):
# 根据ID显示文章,ID是整型数据
return 'Post %d' % post_id
if __name__ == '__main__':
app.run(debug=True)

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- int:接收整数
- float:同int,但是接受的是浮点数
- path:和默认的相似,但是也接受斜线



2.2.2 构造URL
Flask能够匹配URL,而且还可以用url_for()来给指定的函数构造URL。它接收函数名作为第一个参数,也接受对应URL规则的变量部分的命名参数。未知变量部分会添加到URL末尾作为查询条件
from flask import Flask , url_for
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/user/')
def show_user_profile(username):
# 显示该用户名的用户信息
return 'User %s' % username
@app.route('/post/')
def show_post(post_id):
# 根据ID显示文章,ID是整型数据
return 'Post %d' % post_id
@app.route('/url/')
def get_url():
# 根据ID显示文章,ID是整型数据
return url_for('show_post',post_id=2)
if __name__ == '__main__':
app.run(debug=True)

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25

2.2.3 HTTP方法
HTTP(与web应用会话的协议)有许多的不同的构造方法访问URL方法。默认情况下,路由只回应GET请求,当时通过route()装饰器传递methods 参数可以改变这个行为。
@app.route('/', methods=['GET', 'POST'])
def index():
if request.methods=='POST':
pass
else:
pass

2.3 静态文件
url_for('static',filename='style.css'),
# 这个文件应该存储在文件系统上的static/style.css
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
return render_template('index.html')
@app.route('/user/')
def show_user_profile(username):
# 显示该用户名的用户信息
return render_template('user.html', name=username)
if __name__ == '__main__':
app.run(debug=True)



2.4 蓝图
蓝图学习




三、模板
模板是一个包含响应文本的额文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道。使用真实值替代变量,再返回最终得到的响应字符串,这一过程称为渲染。为了渲染模板,Flask使用了一个名为Jinja2的强大模板引擎
3.1 渲染模板
默认情况下,Flask在程序文件夹中的templates 子文件夹中寻找模板。
比如:



3.2 变量
我们可以在模板中使用变量{{name}},这表示一个占位符,而name是变量名称;
模板学习
<p>从一个字典中获取一个值:{{mydict['key']}}.p>
<p>从一个列表中获取一个值:{{mylist[3]}}.p>
<p>从一个列表中获取一个带索引的值:{{mylist[myintvar]}}.p>
<p>从一个对象的方法中获取一个值:{{myobj.somemethod()}}.p>
可以使用过滤器修改变量,过滤器添加变量名之后,中间使用竖线分隔。
Hello,{{name|capitalize}}
Jinja2提供了许多内置过滤器,常用的过滤器如下:


3.3 控制结构
3.3.1 条件控制语句
if…else…endif
{% if user %}
Hello,{{user}}
{% else %}
Hello Stranger
{% endif %}
3.3.2 循环语句
{% for comment in comments %}
{{comment}}
{% endfor %}
3.3.3 宏
宏类似于Python代码中的函数
{% macro render_comment(comment) %}
{{comment}}
{% endmacro %}
{% for comment in comments %}
{{render_comment(comment)}}
{% endfor %}
3.3.4 公共代码
需要在多处重复使用的模板代码片段可以写在独立的文件,在包含在所有的模板中,以免重复
方法一:全部包含
{% include 'common.html' %}
方法二:继承包含
base.html
{%block head%}
{%block title%}{%endblock%}-My Application
<%endblock%>
<body>
{%bolck body%}
{%endbody%}
</body>
</html>
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><p>bolck标签定义的元素可在衍生模板中修改。在本例中,我们定义了名为head、title、body的块。注意。title包含在head中。</p>
<p>举例衍生模板</p>
{% extends "base.html"}
{%block title%}Index{%endhead%}
{%block head%}
{<!-- -->{supper()}}
<span><span><span><</span>style</span><span>></span></span><span><span>
</span></span><span><span><span></</span>style</span><span>></span></span>
{% endblock %}
{%bolck body%}
<span><span><span><</span>h1</span><span>></span></span>Hello<span><span><span></</span>h1</span><span>></span></span>
{%endbody%}
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><p>extends 指令声明这个模板衍生于base,html,在extends指令之后,基模板的三个块被重新定义,模板引擎将会在其插入适当的位置,注意新定义的head块,在基模板中其内容不是空的,所以用supper()获取原来的内容</p>
<h2>四、Web表单</h2>
<ul><li>web表单是允许用户和web应用交互的基本元素,FLask自己是不会处理表单的,但是Flask-WTF扩展允许用户在flask应用中使用著名的WTForms包,这个包使得定义表单和处理表单变得简单<br>参考</li></ul><h3>4.1 安装</h3>
pip install flask<span>-</span>wtf
<ul><li>1</li></ul><p>安装成功显示如下:<br><img src="/d/file/p/20240325/e446158ac10e599ddd14117dee8c1730.png" alt="在这里插入图片描述"></p>
<h3>4.2 CSRF的保护和验证</h3>
<p>官网</p>
<p>CSRF跨站请求伪造,源于WEB的隐式身份验证机制。WEB的身份验证机制虽然可以抱着一个请求时来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。</p>
<p>例如,用户登录受信任的网址A,在本地生成了Cookie,在Cookie没有失效的情况下去访问了危险网站B。B可能会盗用你的身份,以你的名义去发送恶意请求,邮件,盗取你的账号,设置购买商品,造成你个人隐私泄露,已经财产安全。</p>
<p>实际上,WTForms在渲染没一个表单都会生成一个独一无二的token,这个token将在POST请求的时候随着表单一起提交进行验证。默认情况下Flask-WTF能保护所有表单免受跨域请求伪造的攻击,恶意网站把请求发送到被攻击者已经登陆的网站就会引发CSRF攻击。为了实现CSRF保护,Flask-WTF需要程序设置加密令牌,再用加密令牌来验证表单数据的真伪。</p>
<p>使用方法</p>
app = Flask(__name__)
app.config['SECRET_KEY'] = 'abcd123'
<ul><li>1</li><li>2</li></ul><ul><li>app.config字典可以存储框架、扩展和程序本身的配置变量。使用标准的字典语法把配置值添加到app.config对象中</li><li>SECRET_KEY配置变量是通用密钥,可在Flask和多个扩展中使用</li></ul><h3>4.3 表单类</h3>
<p>使用Flask-WTF时,每个表单都由一个继承自Form的类表示,这个类定义表单中的一组字段。</p>
<p>每个字段有用对象表示,并且字段可以附属一个或者多个校验用来验证用户输入的数据是否符合要求。</p>
<span>from</span> flask_wtf <span>import</span> FlaskForm
<span>from</span> wtforms <span>import</span> StringField<span>,</span> PasswordField<span>,</span> SubmitField
<span>from</span> wtforms<span>.</span>validators <span>import</span> Required
<span>class</span> <span>NameForm</span><span>(</span><span>)</span><span>:</span>
name <span>=</span> StringField<span>(</span><span>'请输入姓名'</span><span>,</span> validators<span>=</span><span>[</span>Required<span>(</span><span>)</span><span>]</span><span>)</span>
password <span>=</span> PasswordField<span>(</span><span>'请输入密码'</span><span>,</span> validators<span>=</span><span>[</span>Required<span>(</span><span>)</span><span>]</span><span>)</span>
submit <span>=</span> SubmitField<span>(</span><span>'Submit'</span><span>)</span>
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><p>这个表单中所有字段都定义为类变量,类变量的值是相应字段类型的对象<br><img src="/d/file/p/20240325/2cd9012e6702fcf646944556f9340bbe.png" alt="在这里插入图片描述"><br> 在上述代码中我们使用了三个HTML标准字段,更多参考如下:<br><img src="/d/file/p/20240325/ae9bb3d23ba074080ce011e891c0ce7d.png" alt="在这里插入图片描述"><br><img src="/d/file/p/20240325/d765bb0dac2b02191472f00c28fb5f48.png" alt="在这里插入图片描述"></p>
<h3>4.4 把表单渲染成HTML</h3>
<p>表单字段是可调用的,在模板中渲染会生成HTML。</p>
<p>假设视图函数把一个NameForm实力通过参数传进form表单,在模板中可以生成一个简单的表单验证用户登录信息。</p>
<p>创建一个model.py文件定义一个表单类LoginForm,其中有三个属性分别是name,password和submit,具体代码如下:</p>
<span>from</span> flask_wtf <span>import</span> FlaskForm
<span>from</span> wtforms <span>import</span> StringField<span>,</span> PasswordField<span>,</span>SubmitField
<span>from</span> wtforms<span>.</span>validators <span>import</span> DataRequired<span>,</span>Length
<span>class</span> <span>LoginForm</span><span>(</span>FlaskForm<span>)</span><span>:</span>
<span>"""
登录表单类
"""</span>
name <span>=</span> StringField<span>(</span>label<span>=</span><span>'用户名'</span><span>,</span> validators<span>=</span><span>[</span>
DataRequired<span>(</span><span>"用户名不能为空"</span><span>)</span><span>,</span>
Length<span>(</span><span>max</span><span>=</span><span>10</span><span>,</span><span>min</span><span>=</span><span>3</span><span>,</span>message<span>=</span><span>"用户名长度必须大于3且小于8"</span><span>)</span>
<span>]</span><span>)</span>
password <span>=</span> PasswordField<span>(</span>label<span>=</span><span>'密码'</span><span>,</span> validators<span>=</span><span>[</span>
DataRequired<span>(</span><span>"密码不能为空"</span><span>)</span><span>,</span>
Length<span>(</span><span>max</span><span>=</span><span>10</span><span>,</span> <span>min</span><span>=</span><span>6</span><span>,</span> message<span>=</span><span>"用户名长度必须大于6且小于10"</span><span>)</span>
<span>]</span><span>)</span>
submit <span>=</span> SubmitField<span>(</span>label<span>=</span><span>"提交"</span><span>)</span>
<span data-report-view='{"spm":"1001.2101.3001.7365"}'><img src="/d/file/p/20240325/a4cad9b5dc3d5cf772309246a278bf68.png" alt="" title=""></span><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li></ul><p>在文件中分别创建首页视图index()函数和登录页视图login()函数。引入我们刚才创建的model.py文件并在login()视图函数中对用户登陆进行验证,验证通过则跳转至首页,否则提示错误</p>
<span>from</span> flask <span>import</span> Flask <span>,</span>url_for<span>,</span>redirect<span>,</span> render_template
<span>from</span> models <span>import</span> LoginForm
app <span>=</span> Flask<span>(</span>__name__<span>)</span>
app<span>.</span>config<span>[</span><span>'SECRET_KEY'</span><span>]</span> <span>=</span> <span>'mrsoft'</span>
<span>@app<span>.</span>route</span><span>(</span><span>'/login'</span><span>,</span> methods<span>=</span><span>[</span><span>'GET'</span><span>,</span> <span>'POST'</span><span>]</span><span>)</span>
<span>def</span> <span>login</span><span>(</span><span>)</span><span>:</span>
<span>"""
登录页面
"""</span>
form <span>=</span> LoginForm<span>(</span><span>)</span>
<span>if</span> form<span>.</span>validate_on_submit<span>(</span><span>)</span><span>:</span>
username <span>=</span> form<span>.</span>name<span>.</span>data
password <span>=</span> form<span>.</span>password<span>.</span>data
<span>if</span> username<span>==</span> <span>"admin"</span> <span>and</span> password <span>==</span> <span>"abcd1234"</span><span>:</span>
<span>return</span> redirect<span>(</span>url_for<span>(</span><span>'index'</span><span>)</span><span>)</span>
<span>return</span> render_template<span>(</span><span>'login.html'</span><span>,</span>form<span>=</span>form<span>)</span>
<span>@app<span>.</span>route</span><span>(</span><span>'/'</span><span>)</span>
<span>def</span> <span>index</span><span>(</span><span>)</span><span>:</span>
<span>"""
首页
"""</span>
name <span>=</span> <span>"班德尔城"</span>
message <span>=</span> <span>"""
约德尔人的故乡究竟在何处?对于这个问题人们众说纷纭,不过有一些凡人声称自己穿过了无形的传送门,进入了超越物质领域的奇异魔法世界。他们都描述了一个魔法奔放的地方,鲁莽蛮横的人会被无数的奇观带入歧途,最后迷失在梦境中,永远无法返回……
在班德尔城,任何约德尔人以外的种族都会感到自己的全部感官得到了强化。城中所见无不色彩斑斓,食物与水的味道让人经年沉醉——只要尝过一次,就终身难忘。这里日光溶溶,春水不休,每一株植物都会结出累累硕果。或许这些描述中有一部分属实,或许全都是假的——因为没有任何两个讲述者能够对所见所闻达成一致。
只有一件事可以肯定,那就是班德尔城和里面的居民都具有某种超脱时间的属性,这或许可以解释为什么从那里回来的凡人全都像是一夜苍老了许多年岁,更多人则根本是一去不复返。
"""</span>
<span>return</span> render_template<span>(</span><span>"index.html"</span><span>,</span>name<span>=</span>name<span>,</span>message<span>=</span>message<span>)</span>
<span>if</span> __name__ <span>==</span> <span>'__main__'</span><span>:</span>
app<span>.</span>run<span>(</span>debug<span>=</span><span>True</span><span>,</span>
port<span>=</span><span>8000</span><span>)</span>
<span data-report-view='{"spm":"1001.2101.3001.7365"}'><img src="/d/file/p/20240325/a4cad9b5dc3d5cf772309246a278bf68.png" alt="" title=""></span><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li></ul><p>渲染login.html和index.html如下:</p>
<span><</span>div <span>class</span><span>=</span><span>"jumbotron"</span><span>></span>
<span><</span>form action<span>=</span><span>""</span> method<span>=</span><span>"post"</span><span>></span>
<span><</span>div <span>class</span><span>=</span><span>"form-group"</span><span>></span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>name<span>.</span>label <span>}</span><span>}</span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>name<span>(</span><span>class</span><span>=</span><span>"form-control"</span><span>)</span><span>}</span><span>}</span>
<span>{<!-- --></span><span>%</span> <span>for</span> err <span>in</span> form<span>.</span>name<span>.</span>errors <span>%</span><span>}</span>
<span><</span>p style<span>=</span><span>"color: red"</span><span>></span><span>{<!-- --></span><span>{<!-- --></span> err <span>}</span><span>}</span><span><</span><span>/</span>p<span>></span>
<span>{<!-- --></span><span>%</span> endfor <span>%</span><span>}</span>
<span><</span><span>/</span>div<span>></span>
<span><</span>div <span>class</span><span>=</span><span>"form-group"</span><span>></span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>password<span>.</span>label <span>}</span><span>}</span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>password<span>(</span><span>class</span><span>=</span><span>"form-control"</span><span>)</span> <span>}</span><span>}</span>
<span>{<!-- --></span><span>%</span> <span>for</span> err <span>in</span> form<span>.</span>password<span>.</span>errors <span>%</span><span>}</span>
<span><</span>p style<span>=</span><span>"color: red"</span><span>></span><span>{<!-- --></span><span>{<!-- --></span> err <span>}</span><span>}</span><span><</span><span>/</span>p<span>></span>
<span>{<!-- --></span><span>%</span> endfor <span>%</span><span>}</span>
<span><</span><span>/</span>div<span>></span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>csrf_token <span>}</span><span>}</span>
<span>{<!-- --></span><span>{<!-- --></span> form<span>.</span>submit<span>(</span><span>class</span><span>=</span><span>"btn btn-primary"</span><span>)</span> <span>}</span><span>}</span>
<span><</span><span>/</span>form<span>></span>
<span><</span><span>/</span>div<span>></span>
<span data-report-view='{"spm":"1001.2101.3001.7365"}'><img src="/d/file/p/20240325/a4cad9b5dc3d5cf772309246a278bf68.png" alt="" title=""></span><ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul>
<span><</span>div <span>class</span><span>=</span><span>"jumbotron"</span><span>></span>
<span><</span>h1 <span>class</span><span>=</span><span>"display-3"</span><span>></span>欢迎来到<span>{<!-- --></span><span>{<!-- --></span>name<span>}</span><span>}</span><span><</span><span>/</span>h1<span>></span>
<span><</span>p <span>></span>
<span>{<!-- --></span><span>{<!-- --></span>message<span>}</span><span>}</span>
<span><</span><span>/</span>p<span>></span>
<span><</span>hr <span>class</span><span>=</span><span>"my-4"</span><span>></span>
<span><</span>p<span>></span>
<span><</span>a <span>class</span><span>=</span><span>"btn btn-primary btn-lg"</span> href<span>=</span><span>"#"</span> role<span>=</span><span>"button"</span><span>></span>了解更多<span><</span><span>/</span>a<span>></span>
<span><</span><span>/</span>p<span>></span>
<span><</span><span>/</span>div<span>></span>
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul><p>当我们运行run.py函数,浏览器输入</p>
<p>http://127.0.0.1:5000/login</p>
<p><img src="/d/file/p/20240325/d323343010a3749d67034084a02c4a7d.png" alt="在这里插入图片描述"><br> 如果用户没有填入值就直接提交,DataRequired就会捕获这个异常</p>
<p><img src="/d/file/p/20240325/31e15ff26ba9f7587b5f83886e045399.png" alt="在这里插入图片描述"><br> 如果用户密码长度不满足要求,length()函数就会捕获这个异常<br><img src="/d/file/p/20240325/d12821fe021f1fe5d313c05b6653a1fe.png" alt="在这里插入图片描述"><br> 密码输入无误,则会成功跳转至首页<br><img src="/d/file/p/20240325/f950642e53fa1d2dab6c87b6a2a07865.png" alt="在这里插入图片描述"></p>
</div>
<div class="pagebar"> </div>
<div class="tags_share">
<div class="artice_tags"> <span>标签:</span>
</div>
</div>
<div class="avow">
<div class="avowtitle">声明</div>
<!-- 声明 -->
<p>1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。</p>
<p>在线投稿:<a href='https://www.pyhost.cn/e/DoInfo/AddInfo.php?classid=2&mid=1&ecmscheck=1' target='_blank'>投稿</a> 站长QQ:1888636</p>
<!-- @声明 -->
</div>
<div class="pcd_ad"><script src="/skin/js/thea7.js"></script></div>
<div class="mbd_ad"><table width="100%" height="90" style="background-color:#ccc;">
<tr align="center">
<td style="text-align: center;color: #666;">后台-插件-广告管理-内容页尾部广告(手机)</td>
</tr>
</table></div>
<div class="related">
<div class="md_tit"> <span>相关文章</span> </div>
<ul>
<li><a href="/tutorial/5402.html" title="08 | Swoole与Go系列教程之Channel通道的应用">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="08 | Swoole与Go系列教程之Channel通道的应用"></div>
<p>08 | Swoole与Go系列教程之Channel通道的应用</p>
</a>
</li>
<li><a href="/tutorial/5403.html" title="thinkphp融合workerman的两种简单方式,直接在workerman里面用tp的orm功能">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="thinkphp融合workerman的两种简单方式,直接在workerman里面用tp的orm功能"></div>
<p>thinkphp融合workerman的两种简单方式,直接在workerman里面用tp的orm功能</p>
</a>
</li>
<li><a href="/tutorial/5397.html" title="[240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="[240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告"></div>
<p>[240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告</p>
</a>
</li>
<li><a href="/tutorial/5396.html" title="Typecho:简约而强大的开源PHP博客平台">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="Typecho:简约而强大的开源PHP博客平台"></div>
<p>Typecho:简约而强大的开源PHP博客平台</p>
</a>
</li>
<li><a href="/tutorial/5387.html" title="昔日辉煌不再,PHP老矣,尚能饭否?">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="昔日辉煌不再,PHP老矣,尚能饭否?"></div>
<p>昔日辉煌不再,PHP老矣,尚能饭否?</p>
</a>
</li>
<li><a href="/tutorial/5384.html" title="PHP APCu缓存使用与避坑">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="PHP APCu缓存使用与避坑"></div>
<p>PHP APCu缓存使用与避坑</p>
</a>
</li>
<li><a href="/tutorial/5381.html" title="谁说PHP不能异步和并行运行?">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="谁说PHP不能异步和并行运行?"></div>
<p>谁说PHP不能异步和并行运行?</p>
</a>
</li>
<li><a href="/tutorial/5377.html" title="一个用rust写的类似于Skywalking/CAT的迷你trace PHP扩展">
<div class="img"><img src="" onerror="this.onerror=null; this.src='/skin/images/def.jpeg'" alt="一个用rust写的类似于Skywalking/CAT的迷你trace PHP扩展"></div>
<p>一个用rust写的类似于Skywalking/CAT的迷你trace PHP扩展</p>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="main_right" id="main_right">
<div class="widget widget_gzwmdiy">
<div class="md_tit"><span>关注我们</span></div>
<div class="widget_gz_body">
<p>扫一扫关注我们,了解最新精彩内容</p>
<div class="qr_img"> <img src="/d/file/p/20231220/8ad98652841054fbbc542cb0219b1219.png" alt=""> </div>
</div>
</div>
<div class="widget widget_searchpanel">
<div class="md_tit"><span>搜索</span></div>
<div class="widget_div">
<form onsubmit="return checkSearchForm()" method="post" name="searchform" action="/e/search/index.php" >
<input type="text" name="keyboard" placeholder="输入关键词"/>
<button type="submit" class="submit" value="搜索"><i class="fa fa-search"></i></button>
<input type="hidden" value="title" name="show">
<input type="hidden" value="1" name="tempid">
<input type="hidden" value="news" name="tbname">
<input name="mid" value="1" type="hidden">
<input name="dopost" value="search" type="hidden">
</form>
</div>
</div>
<div class="widget widget_cead">
<script src="/skin/js/thea3.js"></script>
</div>
<div class="widget widget_paihang">
<div class="md_tit"><span>排行榜</span></div>
<script>$( function () {$( '.paihang' ).tabslet();} );</script>
<div class="paihang">
<ul class="tit">
<li><a href="#hot_1">热门文章</a></li>
<li><a href="#hot_2">随机文章</a></li>
</ul>
<div id="hot_1" class="ph_list">
<ul>
<li><a href="/tutorial/1009.html" target="_blank">好奇喵 | Tor浏览器——如何拥有一颗洋葱并使用</a></li>
<li><a href="/tutorial/2921.html" target="_blank">Ubuntu 20.04 RTX 4090显卡 深度学习环境配置(Nvidia显卡驱动、CUDA11.6.0、cuDNN8.5)</a></li>
<li><a href="/tutorial/1594.html" target="_blank">VPN的介绍及自建点对点的OpenVPN和使用方法:保姆级详细教程,(windou客户端版)后附脚本</a></li>
<li><a href="/tutorial/126.html" target="_blank">phpy :PHP 与 Python 互调用库,为 PHP 引入 Python 生态,PHP 也可以写 AI 了</a></li>
<li><a href="/tutorial/120.html" target="_blank">Linux内核开启BBRv3加速让VPS更低延迟提升性能</a></li>
<li><a href="/tutorial/1819.html" target="_blank">【R语言】——基因GO/KEGG富集分析!超级简单的保姆级教程!</a></li>
<li><a href="/tutorial/2192.html" target="_blank">Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO</a></li>
<li><a href="/tutorial/164.html" target="_blank">如何快速定位当前数据库消耗 CPU 最高的sql 语句?</a></li>
<li><a href="/tutorial/4398.html" target="_blank">Element Plus 虚拟化表格组件的使用(排序、筛选、自定义单元格渲染) - 个人使用总结</a></li>
</ul>
</div>
<div id="hot_2" class="ph_list">
<ul>
<li><a href="/tutorial/4921.html" target="_blank">前端实现websocket通信讲解(vue2框架)</a></li>
<li><a href="/tutorial/4794.html" target="_blank">Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(二)项目实现-第二篇-前端模块搭建及单点登录的实现</a></li>
<li><a href="/tutorial/4171.html" target="_blank">自动化进阶之路,selenium中webdriver的ChromeOptions参数说明</a></li>
<li><a href="/tutorial/1869.html" target="_blank">第五篇【传奇开心果系列】Python的自动化办公库技术点案例示例:深度解读Pandas在教育数据和研究数据处理领域的应用</a></li>
<li><a href="/tutorial/1352.html" target="_blank">Latex笔记:引用子图(subfigure)不出现Fig 5(a)的(a),如何解决?</a></li>
<li><a href="/tutorial/1572.html" target="_blank">基于微信小程序的购物系统+php</a></li>
<li><a href="/tutorial/896.html" target="_blank">Docker的配置和部署,并搭建php和nginx环境</a></li>
<li><a href="/tutorial/1121.html" target="_blank">基于SpringBoot的个人网盘系统+92922(免费领源码、附论文)可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C++、python、数据可视化、大数据、全套文案</a></li>
<li><a href="/tutorial/4287.html" target="_blank">HTML学习笔记 1-用HBuilderX写的HTML无法在浏览器上运行怎么办?问题出在这里:HBuilderX外部web服务支撑配置</a></li>
</ul>
</div>
</div>
</div>
<div class="widget widget_cead">
<script src="/skin/js/thea4.js"></script>
</div>
<div class="widget widget_previous">
<div class="md_tit"><span>最近发表</span></div>
<ul>
<li><a title="08 | Swoole与Go系列教程之Channel通道的应用" href="/tutorial/5402.html">08 | Swoole与Go系列教程之Channel通道的应用</a></li>
<li><a title="thinkphp融合workerman的两种简单方式,直接在workerman里面用tp的orm功能" href="/tutorial/5403.html">thinkphp融合workerman的两种简单方式,直接在workerman里面用tp的orm功能</a></li>
<li><a title="[240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告" href="/tutorial/5397.html">[240607] Jina AI 发布多模态嵌入模型 | PHP 曝新漏洞 | TypeScript 5.5 RC 发布公告</a></li>
<li><a title="Typecho:简约而强大的开源PHP博客平台" href="/tutorial/5396.html">Typecho:简约而强大的开源PHP博客平台</a></li>
<li><a title="昔日辉煌不再,PHP老矣,尚能饭否?" href="/tutorial/5387.html">昔日辉煌不再,PHP老矣,尚能饭否?</a></li>
<li><a title="PHP APCu缓存使用与避坑" href="/tutorial/5384.html">PHP APCu缓存使用与避坑</a></li>
<li><a title="谁说PHP不能异步和并行运行?" href="/tutorial/5381.html">谁说PHP不能异步和并行运行?</a></li>
<li><a title="一个用rust写的类似于Skywalking/CAT的迷你trace PHP扩展" href="/tutorial/5377.html">一个用rust写的类似于Skywalking/CAT的迷你trace PHP扩展</a></li>
<li><a title="Typecho博客搭建教程" href="/tutorial/5374.html">Typecho博客搭建教程</a></li>
</ul>
</div>
<div class="widget widget_cead">
<script src="/skin/js/thea5.js"></script>
</div>
<div class="widget widget_tags">
<div class="md_tit"><span>标签列表</span></div>
<ul>
<li><a target="_blank" href="/tags-优惠促销-0.html">优惠促销</a></li>
<li><a target="_blank" href="/tags-香港VPS-0.html">香港VPS</a></li>
<li><a target="_blank" href="/tags-美国VPS-0.html">美国VPS</a></li>
<li><a target="_blank" href="/tags-洛杉矶-0.html">洛杉矶</a></li>
<li><a target="_blank" href="/tags-洛杉矶VPS-0.html">洛杉矶VPS</a></li>
<li><a target="_blank" href="/tags-新加坡vps-0.html">新加坡vps</a></li>
<li><a target="_blank" href="/tags-优惠码-0.html">优惠码</a></li>
<li><a target="_blank" href="/tags-服务器-0.html">服务器</a></li>
<li><a target="_blank" href="/tags-美国CN2VPS-0.html">美国CN2VPS</a></li>
<li><a target="_blank" href="/tags-便宜美国vps-0.html">便宜美国vps</a></li>
<li><a target="_blank" href="/tags-美国vps推荐-0.html">美国vps推荐</a></li>
<li><a target="_blank" href="/tags-日本vps-0.html">日本vps</a></li>
<li><a target="_blank" href="/tags-美国便宜VPS-0.html">美国便宜VPS</a></li>
<li><a target="_blank" href="/tags-独立服务器-0.html">独立服务器</a></li>
<li><a target="_blank" href="/tags-VPS-0.html">VPS</a></li>
<li><a target="_blank" href="/tags-香港vps推荐-0.html">香港vps推荐</a></li>
<li><a target="_blank" href="/tags-美国vpscn2-0.html">美国vpscn2</a></li>
<li><a target="_blank" href="/tags-香港cn2vps-0.html">香港cn2vps</a></li>
<li><a target="_blank" href="/tags-美国cmin2vps-0.html">美国cmin2vps</a></li>
<li><a target="_blank" href="/tags-美国as9929vps-0.html">美国as9929vps</a></li>
</ul>
</div>
</div>
</div>
<!-- # main_body -->
</div>
</div>
<div id="footer">
<div class="footer container">
<div class="fr"><a href="/contact/" target="_blank">申请友情链接</a></div>
<div class="fl">
<p>Copyright (c) 2023 主机评测 All rights reserved. <a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow">浙ICP备2022012306号-1</a> </p>
</div>
</div>
</div>
<div class="m_search"><i class="fa fa-search"></i></div>
<div class="m_search_box"> <span><i class="fa fa-remove"></i></span>
<form onsubmit="return checkSearchForm()" method="post" name="searchform" action="/e/search/index.php" >
<input type="text" name="keyboard" placeholder="输入关键词"/>
<button type="submit" class="submit" value="搜索"><i class="fa fa-search"></i></button>
<input type="hidden" name="show" value="title,newstext">
<input type="hidden" name="tempid" value="1">
<input type="hidden" value="news" name="tbname">
<input name="mid" value="1" type="hidden">
<input name="dopost" value="search" type="hidden">
</form>
</div>
<div id="goTop" class="goTop"><i class="fa fa-angle-up"></i></div>
<script src="/skin/js/common.min.js" type="text/javascript"></script>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f87360bc08657de9dda1d3005636bdbe";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>