热门IT资讯网

《Flask Web开发:基于Python的Web应用开发实战》笔记二、

发表于:2024-11-25 作者:热门IT资讯网编辑
编辑最后更新 2024年11月25日,第三章、模板 视图函数作用即生成请求的响应,如果把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。吧表现逻辑转移到模板中能够提升程序的可维护性。 模板是一个响应文本的文件,其中包含用占位变量表示的

第三章、模板

 视图函数作用即生成请求的响应,如果把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。吧表现逻辑转移到模板中能够提升程序的可维护性。
 模板是一个响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文才能知道。
 使用真实值替换变量,在返回最终得到的响应字符串,这一过程称为渲染。

3.1、Jinja2模板引擎

3.1.1、渲染模板

 在默认情况下,Flask程序会在templates子文件夹中寻找模板。在下一个hello.py版本中,要把前面定义的模板保存在templates文件夹中,并分别命名为index.html和user.html。

from flask import Flask,render_templatefrom flask_script import Managerapp = Flask(__name__)manager = Manager( app )@app.route('/')def index():    return render_template('index.html')@app.route('/user/')def user(name):    return render_template('user.html',name=name)if __name__ == "__main__":   manager.run()
  •  代码详解:Flask提供的render_template函数吧Jinja2模板引擎集成到程序中。render_template函数的第一个参数是模板的文件名,随后的参数都是键值对,表示模板中变量对应的真实值。

3.1.2、变量

  •  Jinja2能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板中使用变量的一些示例如下:

    DICT {{ mydict['key'] }}

    LIST {{ mylist[3] }}

    list with a variable index: {{ mylist[myintvar]}}

    object's method: {{ myobj.somemethod() }}

  • 常用Jinja2 变量过滤器
  1. safe 渲染值时不转义
  2. capitalize 把值的首字母转换成大写,其他字母转换成小写
  3. lower 把值转换成小写形式
  4. upper 把值转换成大写形式
  5. title 把值中每个单词的首字母都转换成大写
  6. trim 把值的首尾空格去掉
  7. striptags 渲染之前把值中所有的HTML标签都删掉

3.1.3、控制结构

条件控制语句
{% if user %}
{% else %}
{% endif %}
for循环语句
{% for comment in comments %}
{% endfor %}
支持宏
{% marco render_comment(comment) %}
多处重复使用的模板代码片段可以写入单独的文件,再包含在所有的模板中,以避免重复:
{ % include 'comment.html' %}

  •  另外一中重复使用代码的强大方式是模板继承,他类似于Python代码中的类继承。继承方式如下:首先创建一个名为base.html的基础模板:
    {% block head %}{% block title %}{% endblock %}- My Application{% endblock %}{% block body %}{% endblock %}    
  •  block标签定义的元素可在衍生的模板中年修改。在本例中,我们定义了名为head,title,body的块元素。注意,title包含在head中。下面就是基于基础模板的衍生模板:
    {% extends bash.html %}{% block title %}Index{% endblock%}{% block head%}{{ super() }}{% endblock %}{% block body %}

    hello,world

    {% endblock %}
  •  extends指令声明这个模板衍生自base.htmk,在extends指令之后,基础模板中的3个板块重新定义,模板引擎会贾汪其插入适当的位置。注意新定义head块,在基础模板中内容是空的,所以使用super()获取原来的内容。

3.2、使用Flask-Bootstrap集成Twitter Bootstrap

  Bootstrap是Twitter开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,并且这些网页还能兼容所有现代的Web浏览器。
 Bootstrap是客户端框架,不会直接涉及服务器。要下在程序中继承Bootstrap,显然需要对模板做所有必要的改动,更简单的方法就是安装Flask-Bootstrap的Flask扩展,简化集成的过程。

  • Flask-Bootstrap使用pip方式安装
    pip install flask-bootstrap
  • Flask扩展一般在创建程序实例时初始化。

    from flask.ext.bootstrap import Bootstrapbootstrap = Bootstrap(app)
  • templates/user.html,使用的就是Flask-Bootstrap的模板
    {% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block navbar %}{% endblock %}{% block content %}
    {% endblock %}

代码详解:

  •  Jinja2中的extends指令从Flask-Bootstrap中导入bootstrap/base.html,从而实现模板继承。Flask-Bootstrap中的基础模板提供了一个网页框架,引入了Bootstrap中的所有CSS和JavaScript文件。
  •   基础模板中定义了可在衍生模板中重新定义的块。block和endblock指令定义块中的内容可添加到基模板中。

Flaks-Bootstrap基模板中定义的块:
块名 说明

  1. doc 整个HTML文档
  2. html_attribs 标签的属性
  3. html 标签的内容
  4. head 标签中的内容
  5. title 标签中的内容</li><li>metas 一组<meta>标签</li><li>styles 层叠样式表定义</li><li>body_attribs <body>标签的属性</li><li>body <body>标签中的内容</li><li>navbar 用户定义的导航条</li><li>content 用户定义的页面内容</li><li>scripts 文档底部的JavaScript声明</li></ol></blockquote><h3>3.3、自定义错误页面</h3><blockquote><p>Flask允许程序使用基于模板的自定义错误页面,最常见的错误代码有两个:<br>404,客户端请求未知页面或路由时显示。<br>500,有未处理的异常时显示。</p></blockquote><ul><li>自定义错误页面:</li></ul><pre><code>@app.errorhandler(404)def page_not_found(e): return render_template('404.html'),404@app.errorhandler(500)def internal_server_error(e): return render_templte('500.html'),500 </code></pre><ul><li>  和视图函数一样,错误处理程序也返回响应,它们还返回与该错误对应的数字状态码。</li><li>  如果从Github上克隆了这个程序的Git仓库,执行git checkout 3c签出这个程序的这个版本。</li></ul><h3>3.4、链接</h3><blockquote><p> 在模板中直接编写简单路由的URL连接不难,但对于包含可变部分的动态路由,在模板中构建正确的URL就很困难;并且直接编写URL会对代码中定义的路由产生不必要的依赖。<br> Flask提供了url_for()辅助函数,可以使用程序URL映射中保存的信息生成URL。<br> url_for()函数最简单的用法是以视图函数名(后者app.add_url_route()定义路由时使用的端点名)作为参数,返回对应的URL。<br> 使用<strong>url_for()</strong>生成动态地址时,将动态部分作为关键字参数传入。例如,url_for('user',name='john',_external=True)的返回结果是http://localhost:5000/user/john<br> <strong>传入url_for()的关键字参数不仅限于动态路由中的参数。函数能将任何额外参数添加到查询字符串中。</strong>例如,url_for('index',page=2)的返回结果是/?page=2</p></blockquote><h3>3.5、静态文件</h3><blockquote><p> 默认设置下,Flask在程序根目录中名为static的子目录中寻找静态文件。如果需要,可在static文件夹中使用子文件夹存放文件。</p></blockquote><h3>3.6、使用Flask-Monment本地化日期和时间</h3><blockquote><p> 问题背景:如果Web程序的用户来自世界各地,那么处理日期和时间就不是一个简单的任务。<br> 解决方法:通过使用JavaScript开发的优秀客户端开源代码库,名为moment.js,可以在浏览器中渲染日期和时间。Flask-Monment是一个Flask程序扩展。能把moment.js集成到Jinja2模板中。</p></blockquote><ul><li><p>Flask-Moment可以通过pip安装:</p><pre><code>pip install flask-moment</code></pre></li><li>初始化Flask-Moment:<pre><code>from flask.ext.moment import Momentmoment = Moment(app)</code></pre></li><li>除了moment.js,Flask-Moment还依赖jquery.js.Bootstrap已经引入了jquery.js,因此只需引入moment.js即可。<pre><code>{% block scripts %}{{ super() }}{{ moment.include_moment() }}{% endblcok %}</code></pre></li><li>为了处理时间戳,Flask-Moment想模板开放了moment类,后台可以将utc时间传到前台进行渲染。<pre><code>from datetime improt datetime@app.route('/')def index():return render_template('index.html',current_time=datetime.utcnow())</code></pre></li><li>在模板中渲染current_time<pre><code><p>The local date and time is {{ moment(current_time).format('LLL) }}</p><p>That was {{ moment(current_time).fromNow(refresh=True) }}</p></code></pre></li></ul><blockquote><p>更多moment.js用法:http://momentjs.com/docs/#/displaying/<br>Flask-Moment假定服务器端程序处理的时间是"纯正的"datetime对象,且使用UTC表示。</p></blockquote><h2>第四章、Web表单</h2><blockquote><p> 对于一些重复操作(生成表单的HTML代码和验证提交的表单数据),Flask-WTF扩展可以把处理Web表单的过程变成一种愉悦的体验。这个扩展对独立的WTForms包进行了包装,方便集成到Flask程序中。<br>WTForms官网:http://wtforms.simplecodes.com</p></blockquote><ul><li>Flask-WTF及其依赖可使用pip安装:<pre><code>pip install flaks-wtf</code></pre></li></ul><h3>4.1、跨站请求伪造保护</h3><blockquote><p> 默认情况,Flask-WTF能保护所有表单面授跨站请求伪造(CSRF)的***。为了实现CSRF保护,Flask-WTF需要程序设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。</p></blockquote><p><strong>示例代码(设置Flask-WTF):</strong></p><pre><code>app = Flask(__name__)app.config['SECRET_KEY'] = 'hard to guess string'</code></pre><ul><li> 代码详解:app.config字典可用来存储框架、扩展和程序本身的配置变量</li><li> SECRET_KEY配置变量是通用密钥,可在Flask和多个第三方扩展中使用。</li></ul><h3>4.2、表单类</h3><blockquote><p>使用Flask-WTF时,每个Web表单都由一个继承自Form的类表示。</p></blockquote><p><strong>示例代码(一个简单的Web表单,包含一个文本字段和一个提交按钮):</strong></p><pre><code>from flaks.ext.wtf import Formfrom wtforms import StringField,SubmitFieldfrom wtforms.validators import Requiredclass NameForm(Form): name = StringField("What's your name?",validators=[Required()]) submit = SubmitField('Submit')</code></pre><ul><li> 代码详解:StringField类表示属性为type="text"的<input>元素;SubmitField类表示属性为type="submit"的<input>元素。StringField构造函数中的可选参数validators指定一个由验证函数组成的列表,在接收用户提交的数据之前验证数据。验证函数Required()确保提交的字段不为空</li><li> Form基类由Flask-WTF扩展定义,从falsk.ext.wtf中导入。字段和验证函数可以直接从WTForms包中导入。</li></ul><blockquote><p><strong>WTForms支持的HTML标准字段</strong></p><ol><li>StringField 文本字段</li><li>TextAreaField 多行文本字段</li><li>PasswordField 密码文本字段</li><li>HiddenField 隐藏文本字段</li><li>DateField 文本字段,值为 datetime.date 格式</li><li>DateTimeField 文本字段,值为 datetime.datetime 格式</li><li>IntegerField 文本字段,值为整数</li><li>DecimalField 文本字段,值为 decimal.Decimal</li><li>FloatField 文本字段,值为浮点数</li><li>BooleanField 复选框,值为 True 和 False</li><li>RadioField 一组单选框</li><li>SelectField 下拉列表</li><li>SelectMultipleField 下拉列表,可选择多个值</li><li>FileField 文件上传字段</li><li>SubmitField 表单提交按钮</li><li>FormField 把表单作为字段嵌入另一个表单</li><li>FieldList 一组指定类型的字段</li></ol><p><strong>WTForms验证函数</strong></p><ol><li>Email 验证电子邮件地址</li><li>EqualTo 比较两个字段的值;常用于要求输入两次密码进行确认的情况</li><li>IPAddress 验证 IPv4 网络地址</li><li>Length 验证输入字符串的长度</li><li>NumberRange 验证输入的值在数字范围内</li><li>Optional 无输入值时跳过其他验证函数</li><li>Required 确保字段中有数据</li><li>Regexp 使用正则表达式验证输入值</li><li>URL 验证 URL</li><li>AnyOf 确保输入值在可选值列表中</li><li>NoneOf 确保输入值不在可选值列表中</li></ol></blockquote><h3>4.3、把表单渲染成HTML</h3><p><strong>示例代码:(使用Flask-WTF和Flask-Bootstrap渲染表单)</strong></p><pre><code>{% extends 'base.html' %}{% import "bootstrap/wtf.html" as wtf %}{% block title %}Flasky{% endblock %}{% block page_content %}<div class="page-header"><h2>hello,{% if name %}{{ name }}{% else %}Stranger{% endif%}</h2></div>{{ wtf.quick_form(form)}}{% endblock %}</code></pre><ul><li>  代码详解:导入的bootstrap/wtf.html文件定义了一个使用Bootstrap渲染Flask-WTF表单对象的辅助函数。wtf.quick_form()函数的参数为Flask_WTF表单对象,使用Bootstrap的默认样式渲染传入表单。</li></ul><h3>4.4、在视图函数中处理表单</h3><p><strong>示例代码:(视图函数index()不仅要渲染表单,还要接受表单中的数据。)</strong></p><pre><code>@app.route('/',methods=['GET','POST'])def index(): name = None form = NameForm() if form.validate_on_submit(): name = form.name.data form.name.data = '' return render_template('index.html',form=form,name=name) </code></pre><ul><li>代码详解:app.route修饰器中添加的methods参数告诉Flask在URL映射中把这个视图函数注册为GET和POST请求的处理程序。如果没指定methods参数,则默认把视图函数注册为GET请求的处理程序。</li><li> 用户提交表单后,服务器会收到一个POST请求。validate_on_submit()会调用name字段上附属的Required()验证函数。如果名字不为空,就能通过验证,validate_on_submit()返回True。</li></ul><h3>4.5、重定向和用户会话</h3><blockquote><p> 问题背景:当用户输入名字后提交表单,再点击浏览器的刷新按钮,会看到一个警告,关于要求再次提交表单之前进行确认。之所以会出这种问题,是因为刷新页面时浏览器会重新发送之前已经发送过的最后一个请求。<br> 解决方案:<strong>使用重定向作为POST请求的响应</strong>,而不是使用常规响应。重定向是一种特殊的响应,响应内容是URL,而不是包含HTML代码的字符串。浏览器收到这种响应,<strong>会向重定向的URL发起GET请求</strong>,显示页面的内容。<br> 另一问题:如果使用上面的解决方案,程序在处理POST请求时,使用from.name.data获取用户输入的名字,一旦请求结束,数据也就丢失了。所以需要程序将数据存储到用户会话中,在请求之间"记住"数据。用户是一种私有存储,存在每个连接到服务器的客户端中。</p></blockquote><p><strong>示例代码:</strong></p><pre><code>from flask import Flask,render_template,session,redirect,url_for@app.route('/',methods=['GET','POST'])def index(): form = NameForm() if form.validate_on_submit(): session['name'] = form.name.data return redirect(url_for('index')) return render_template('index.html',form=form,name=session.get('name'))) </code></pre><ul><li> 代码详解:合法表单数据的请求最后会调用redirect()函数。<strong>redirect()是个辅助函数</strong>,用来生成HTTP重定向响应。redirect()函数参数是重定向的URL。<strong>url_for()生成URL</strong>,因为这个函数使用URL映射生成URL,从而保证URL和定义的路由兼容,并且修改路由名字后依然可用。</li></ul><h3>4.6、Flash消息</h3><blockquote><p> 问题背景:用户提交了有一项错误的登录表单,服务器发回的响应重新渲染了登录表单,并在表单上面显示信息,提示用户名或密码错误。</p></blockquote><p><strong>示例代码:</strong></p><pre><code>from flask ipmort Flask,render_template,session,redirect,url_for,flash@app.route('/',methods=['GET','POST'])def index(): form = NameForm() if form.validate_on_submit(): old_name = session.get('name') if old_name is not None and old_name != form.name.data: flash("Looks like you have changed your name") session['name'] = olde_name return redirect(url_for('index')) return render_template('index.html',name=session.get('name'),form=form) ```*  代码详解:代码会将每一次提交的名字与上一次**存储在会话中的名字**进行比较,如果两者不一样则会发给客户端下一个响应中显示一个信息。*  仅调用flash()函数并不能把消息显示出来,程序使用的模板要渲染这些信息,最好在基础模板中渲染Flash消息,因为这样所有页面都能使用这些消息。Flask把**get_flashed_messages()函数**开放给模板,用来获取并渲染消息。</code></pre><p>{% block content %}<br><div class="container"><br>{% for message in get_flashed_messages() %}<br><div class="alert alert-warning"><br><button type="button" class="close" data-dismiss="alert"><br>×<br></button><br>{{ message }}<br></div><br>{% endfor %}<br>{% block page_content %}<br>{% endblock %}<br></div><br>{% endblock %}</p> </div> <div class="diggit"><a href="#"> 很赞哦! </a></div> <div class="clear"></div> <div class="keywords"> </div> <div class="share"> <div class="share-text"> <p>转载请说明来源于"热门IT资讯网"</p> <p>本文地址:<a href="https://www.492034.com/a458727" target="_blank">https://www.492034.com/a458727</a></p> </div> </div> <div class="clear"></div> </div> </div> <div class="clear blank"></div> <div class="otherlink whitebg"> <div class="news-title"> <h2>相关文章</h2> </div> <ul> <li><a href="https://www.492034.com/a459863" title="微信自带浏览器跳转appstore失效">微信自带浏览器跳转appstore失效</a></li> <li><a href="https://www.492034.com/a459862" title="PHP接收get、post 、json格式数据">PHP接收get、post 、json格式数据</a></li> <li><a href="https://www.492034.com/a459861" title="Yii2.0框架Restfull API开发攻略">Yii2.0框架Restfull API开发攻略</a></li> <li><a href="https://www.492034.com/a459860" title="PHP 安装于配置">PHP 安装于配置</a></li> <li><a href="https://www.492034.com/a459859" title="App上传应用市场的步骤有哪些能上传哪些应用市场">App上传应用市场的步骤有哪些能上传哪些应用市场</a></li> <li><a href="https://www.492034.com/a459858" title="unity3D与网页的交互---做项目的一点总结">unity3D与网页的交互---做项目的一点总结</a></li> <li><a href="https://www.492034.com/a459857" title="人工智能学习难度大吗 选择Python入门怎么样">人工智能学习难度大吗 选择Python入门怎么样</a></li> <li><a href="https://www.492034.com/a459856" title="原来按下这个按钮,iPhone手机秒变扫描仪,你不会还不知道">原来按下这个按钮,iPhone手机秒变扫描仪,你不会还不知道</a></li> <li><a href="https://www.492034.com/a459855" title="auto_mysqldump_data.sh">auto_mysqldump_data.sh</a></li> <li><a href="https://www.492034.com/a459854" title="利用curl监控web返回状态码监控web service">利用curl监控web返回状态码监控web service</a></li> <!-- <li><a target="_blank" href="/">制作是这么收费的?</a></li> --> </ul> </div> </div> <!-- . end of left-box --> <!-- right aside start--> <aside class="side-section right-box"> <div class="side-tab"> <ul id="sidetab"> <li class="sidetab-current">站长推荐</li> <li>点击排行</li> </ul> <div id="sidetab-content"> <section> <div class="tuijian"> <section class="topnews imgscale"><a href="https://www.492034.com/a459865" title="一季度中国IT安全硬件市场规模同比增长14.5%"><img src="https://www.492034.com/uploadfile/thumb/c9f0f895fb98ab9159f51fd0297e236d/278x185_auto.jpg" alt="一季度中国IT安全硬件市场规模同比增长14.5%"><span>一季度中国IT安全硬件市场规模同比增长14.5%</span></a></section> <ul> <li><a href="https://www.492034.com/a459864" title="小米 MIUI 13.5 升级名单曝光,Android 11 机型或被抛弃"><i><img src="https://www.492034.com/uploadfile/thumb/eccbc87e4b5ce2fe28308fd9f2a7baf3/70x70_auto.jpg" alt="小米 MIUI 13.5 升级名单曝光,Android 11 机型或被抛弃"></i> <p>小米 MIUI 13.5 升级名单曝光,Android 11 机型或被抛弃</p> </a></li> <li><a href="https://www.492034.com/a459859" title="App上传应用市场的步骤有哪些能上传哪些应用市场"><i><img src="https://www.492034.com/uploadfile/thumb/34/66a3b49a.webp" alt="App上传应用市场的步骤有哪些能上传哪些应用市场"></i> <p>App上传应用市场的步骤有哪些能上传哪些应用市场</p> </a></li> <li><a href="https://www.492034.com/a459857" title="人工智能学习难度大吗 选择Python入门怎么样"><i><img src="https://www.492034.com/uploadfile/thumb/6f/151b5a8a.webp" alt="人工智能学习难度大吗 选择Python入门怎么样"></i> <p>人工智能学习难度大吗 选择Python入门怎么样</p> </a></li> <li><a href="https://www.492034.com/a459856" title="原来按下这个按钮,iPhone手机秒变扫描仪,你不会还不知道"><i><img src="https://www.492034.com/uploadfile/thumb/02/7ca1dc6b.webp" alt="原来按下这个按钮,iPhone手机秒变扫描仪,你不会还不知道"></i> <p>原来按下这个按钮,iPhone手机秒变扫描仪,你不会还不知道</p> </a></li> </ul> <section class="topnews imgscale"><a href="https://www.492034.com/a459852" title="关于HTML5的简单理解"><img src="https://www.492034.com/uploadfile/thumb/84/89f54657.webp" alt="关于HTML5的简单理解"><span>关于HTML5的简单理解</span></a></section> <ul> <li><a href="https://www.492034.com/a459846" title="想知道HTML5培训班值不值得去参加"><i><img src="https://www.492034.com/uploadfile/thumb/0d/0af1469c.webp" alt="想知道HTML5培训班值不值得去参加"></i> <p>想知道HTML5培训班值不值得去参加</p> </a></li> <li><a href="https://www.492034.com/a459845" title="客户端热更新框架之UI热更框架设计(下)"><i><img src="https://www.492034.com/uploadfile/thumb/95/ce151df2.webp" alt="客户端热更新框架之UI热更框架设计(下)"></i> <p>客户端热更新框架之UI热更框架设计(下)</p> </a></li> <li><a href="https://www.492034.com/a459836" title="unity3d游戏开发优化简单说明"><i><img src="https://www.492034.com/uploadfile/thumb/b9/2374e783.webp" alt="unity3d游戏开发优化简单说明"></i> <p>unity3d游戏开发优化简单说明</p> </a></li> <li><a href="https://www.492034.com/a459833" title="程序猿的一天"><i><img src="https://www.492034.com/uploadfile/thumb/ec/cb9eba12.webp" alt="程序猿的一天"></i> <p>程序猿的一天</p> </a></li> </ul> </div> </section> <section> <div class="paihang"> <section class="topnews imgscale"><a href="https://www.492034.com/a398653" title="asp后段调用python的方法"><img src="https://www.492034.com/static/assets/images/nopic-5.webp" alt="asp后段调用python的方法"><span>asp后段调用python的方法</span></a></section> <ul> <li><i></i><a href="https://www.492034.com/a248188" title="如何应用AJAX进行注册用户即时检测">如何应用AJAX进行注册用户即时检测</a></li> <li><i></i><a href="https://www.492034.com/a389738" title="Springboot+echarts实现可视化">Springboot+echarts实现可视化</a></li> <li><i></i><a href="https://www.492034.com/a446859" title="ckeditor4.5.1配置图片上传的方法">ckeditor4.5.1配置图片上传的方法</a></li> <li><i></i><a href="https://www.492034.com/a101824" title="Angular中与视图有关的定义有哪些">Angular中与视图有关的定义有哪些</a></li> <li><i></i><a href="https://www.492034.com/a170705" title="织梦自定义表单制作在线订单的方法">织梦自定义表单制作在线订单的方法</a></li> <li><i></i><a href="https://www.492034.com/a100119" title="undo_retention之确定最优的撤销保留时间">undo_retention之确定最优的撤销保留时间</a></li> <li><i></i><a href="https://www.492034.com/a64933" title="以太坊生态系统中的开发工具和技术有哪些">以太坊生态系统中的开发工具和技术有哪些</a></li> <li><i></i><a href="https://www.492034.com/a94442" title="ORA-600:[qertbGetPartitionNumber:qesma2],[],[],[]">ORA-600:[qertbGetPartitionNumber:qesma2],[],[],[]</a></li> </ul> <section class="topnews imgscale"><a href="https://www.492034.com/a44464" title="kbengine+cocos2djs的mmorpg游戏demo是怎么样的"><img src="https://www.492034.com/static/assets/images/nopic-3.webp" alt="kbengine+cocos2djs的mmorpg游戏demo是怎么样的"><span>kbengine+cocos2djs的mmorpg游戏demo是怎么样的</span></a></section> </div> </section> </div> </div> <div class="whitebg cloud"> <h2 class="side-title">标签云</h2> <ul> <a target="_blank" href="https://www.492034.com/tag-100248.html">服务器不能远程桌面</a> <a target="_blank" href="https://www.492034.com/tag-2377870.html">选择外国服务器安全吗</a> <a target="_blank" href="https://www.492034.com/tag-2300001.html">女大学生预防网络安全的措施</a> <a target="_blank" href="https://www.492034.com/tag-2099808.html">网络安全有哪些含金量的证书</a> <a target="_blank" href="https://www.492034.com/tag-102283.html">服务器打开很卡</a> <a target="_blank" href="https://www.492034.com/tag-100027.html">服务器网站模板</a> <a target="_blank" href="https://www.492034.com/tag-100007.html">腾讯云服务器解析域名</a> <a target="_blank" href="https://www.492034.com/tag-2146.html">php 数据库的安全性</a> <a target="_blank" href="https://www.492034.com/tag-126.html">mysql数据库的安全性</a> <a target="_blank" href="https://www.492034.com/tag-2377747.html">服务器云安全费用</a> <a target="_blank" href="https://www.492034.com/tag-100357.html">服务器最大允许连接数</a> <a target="_blank" href="https://www.492034.com/tag-102503.html">云服务器 部署网站</a> <a target="_blank" href="https://www.492034.com/tag-100028.html">linux 跳转服务器</a> <a target="_blank" href="https://www.492034.com/tag-100008.html">服务器可以挖矿吗</a> <a target="_blank" href="https://www.492034.com/tag-200003.html">群晖搭建app服务器</a> <a target="_blank" href="https://www.492034.com/tag-100303.html">deepin 服务器版</a> <a target="_blank" href="https://www.492034.com/tag-278.html">数据库文件安全</a> <a target="_blank" href="https://www.492034.com/tag-2100004.html">校园信息网络安全稳定</a> <a target="_blank" href="https://www.492034.com/tag-1999997.html">幼儿园网络安全教育拍手歌</a> <a target="_blank" href="https://www.492034.com/tag-301072.html">本地怎么连接服务器hive</a> </ul> </div> <div class="clear blank"></div> <div class="whitebg suiji"> <h2 class="side-title">猜你喜欢</h2> <ul> <li><a href="https://www.492034.com/a225529" title="agilent3070软件安装">agilent3070软件安装</a></li> <li><a href="https://www.492034.com/a338912" title="怎么使用纯HTML的通用数据管理和服务">怎么使用纯HTML的通用数据管理和服务</a></li> <li><a href="https://www.492034.com/a393476" title="Python+opencv 实现图片文字的分割的方法示例">Python+opencv 实现图片文字的分割的方法示例</a></li> <li><a href="https://www.492034.com/a339690" title="Files与Paths类怎么在java项目中使用">Files与Paths类怎么在java项目中使用</a></li> <li><a href="https://www.492034.com/a412022" title="查看jupyter文件位置的方法">查看jupyter文件位置的方法</a></li> <li><a href="https://www.492034.com/a326688" title="Python接入MySQL如何实现增删改查">Python接入MySQL如何实现增删改查</a></li> <li><a href="https://www.492034.com/a123239" title="怎么给Linux发行版添加漂亮的字体">怎么给Linux发行版添加漂亮的字体</a></li> <li><a href="https://www.492034.com/a24088" title="uni-app中弹窗的使用与自定义弹窗的方法">uni-app中弹窗的使用与自定义弹窗的方法</a></li> <li><a href="https://www.492034.com/a147264" title="如何解决jvm内存溢出java.lang.OutOfMemoryError: GC overhead limit exceeded问题">如何解决jvm内存溢出java.lang.OutOfMemoryError: GC overhead limit exceeded问题</a></li> <li><a href="https://www.492034.com/a400314" title="java高并发系列 - 第4天:JMM相关的一些概念">java高并发系列 - 第4天:JMM相关的一些概念</a></li> </ul> </div> </aside> <!-- right aside end--> </article> <div class="clear blank"></div> <!--footer start--> <footer> <div class="footer box"> <div class="wxbox"> </div> <div class="endnav"> <p><b>站点声明:</b></p> <p>所有文章未经授权禁止转载、摘编、复制或建立镜像,如有违反,追究法律责任。</p> <p>Copyright © 2009-2024 <a href="https://www.492034.com/" target="_blank">热门IT资讯网</a> All Rights Reserved. <a href="/sitemap.xml">网站地图</a> <a href="/about/">关于我们</a> <a href="/contact-us/">联系我们</a> </p> </div> </div> </footer> <a href="#" title="返回顶部" class="icon-top"></a> <!--footer end--> <div style="display:none"> <!-- site_tongji --> <script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?36c15626b9249e23d6751c6c63858909"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-91HRTP3109"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-91HRTP3109'); </script> <!-- baidu_push --> <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </div> <div style="display:none"> <span class="dr_show_hits_458727">0</span><script type="text/javascript"> $.ajax({ type: "GET", url:"/index.php?s=api&c=module&siteid=1&app=article&m=hits&id=458727", dataType: "jsonp", success: function(data){ if (data.code) { $(".dr_show_hits_458727").html(data.msg); } else { dr_tips(0, data.msg); } } }); </script></div> <!--本页面URL https://www.492034.com/a458727 --> <!--本页面于2024-11-25 00:43:15更新--> </body> </html>