要想开发出易于维护的程序,关键在于编写形式简洁且结构良好的代码。

当目前为止,你看到的示例都太简单,无法说明这一点,但Flask视图函数的两个完全独立的作用却被融合在了一起,这就产生了一个问题。

视图函数的作用很明确,即生成请求的响应。

如第2章中的示例,对简单的请求来所,这就足够了。

但一般而言,请求会改变程序的状态,而这种变化也会在视图函数中产生。

例如,用户在网站中注册一个一个新账户。

用户在表单中输入电子邮箱地址和密码,然后点击提交按钮。

服务器接收到包含用户输入数据的请求,然后Flask把请求分发到处理注册请求的视图函数。

这个视图函数需要访问数据库,添加新用户,然后生成响应回送浏览器。

这两个过程分别称为业务逻辑和表现逻辑。

把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。假设要为一个大型表格构建HTML代码,表格中的数据由数据库中读取的数据以及必要的HTML字符连接在一起。把表现逻辑移到模板中能提升程序的可维护性。

模板是一个包含相应文本的文件,其中包含用占位变来那个表示的动态部分,其具体值只在请求的上下文中才能知道。

使用真实值替换变量,在返回最终的响应字符串,这一过程称为渲染。

为了渲染模板,Flask使用了一个名为Jinja2的强大模板引擎。

3.1 Jinja2模板引擎

形式最简单的Jinja2模板就是一个包含相应文本的文件。

示例 3-1 是一个Jinjia2模板,它和示例 2-1 中的index() 视图函数的响应一样。

示例 3-1 templates/index.html :Jinjia2模板

<h1>Hello World!</h1>

示例 2-2 中,视图函数user() 返回的响应中包含了一个使用变量表示的动态部分。示例 3-2 实现了这个响应。

示例 3-2 template/user.html :Jinjia2模板

<h1>Hello,{{ name }}</h1>

3.1.1 渲染模板

默认情况下,Flask在程序文件夹中的templates子文件夹中寻找模板。

在下一个hello.py版本中,要把前面定义的模板保存在templates文件夹中,并分别命名为 index.html 和 user.html。

程序中的视图函数需要修改一下,以便渲染这些模板。修改方法参见示例 3-3

示例3-3 hello.py :渲染模板

from flask import Flask,render_template# ...

@app.route("/")
def index():                    return render_template('index.html')@app.route("/user/<name>")
def user(name):return render_template('user.html',name=name)

from flask import Flask,render_template
from flask import request
from flask_script import Manager
app = Flask(__name__)
manager = Manager(app)@app.route("/")                    #路由
def index():                    #视图函数return render_template('index.html')@app.route("/user/<name>")        #动态路由
def user(name):return render_template('user.html',name=name)if __name__ == "__main__":manager.run()

View Code

Flask提供的render_template 函数把Jinjia2模板引擎集成到了程序中。

render_template 函数的一个参数是模板的文件名。

随后的参数都是键值对,表示模板中变量对应的真实值。

在这段代码中,第二个模板收到一个名为name的变量。

前例中的 name=name 是关键字参数,这类关键字参数很常见,但如果你不熟悉它们的话,可能会觉得迷惑且难以理解。左边的“name” 表示参数名,就是模板中使用的占位符;右边的“name”是当前作用域中的变量,表示同名参数的值。

3.1.2 变量

示例 3-2 在模板中使用 {{ name }} 结构便是一个变量,它是一种特殊的占位符,告诉模板引擎这个位置的值从渲染模板时使用的数据中获取。

Jinjia2能是被所有类型的变量,设置是一些复杂的类型,例如列表、字典和对象。

在模板中使用变量的一些示例如下:

<p>A value from a dictionary:{{ mydict['key'] }}.</p>
<p>A value from a list:{{ mylist[3] }}.</p>
<p>A value from a list,with a variable index:{{ mylist[myintvar] }}.</p>
<p>A value from an object's method:{{ myobj.somemethod() }}.</p>

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。

例如,下述模板以首字母大写形式显示变量 name 的值:

Hello,{{ name|capitalize }}

表3-1 出了Jinjia2提供的部分常用过滤器。

Jinji2变量过滤器
过滤名 说明
safe 渲染值时不转义
capitalize 把值的首字母装换成大写,其他字母转换成小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中的每个单词的首字符都转换成大写
trim 把值的收尾空格去掉
striptags 渲染之前把值中所有的HTML标签都删掉

safe 过滤器值得特别说明一下。

默认情况下,出于安全考虑,Jinjia2会转义所有变量。

例如,如果一个变量的值为 ‘ <h1>Hello</h1>’,Jinjia2会将其渲染成 ‘&lt; h1&gt;Hello&lt;/h1&gt;’,浏览器能显示这个h1元素,但不会进行解释。

很多情况下需要显示变量中存储的HTML代码,这时就可使用safe过滤器。

注:千万别在不可信的值上用safe 过滤器,例如用户在表单中输入的文本。

完整的过滤器列表可在Jinjia2文档(http://jinja.pocoo.org/docs/templates/#builtin-filters)中查看。

3.1.3 控制结构

Jinjia2提供了多种控制结构,可用来改变模板的渲染流程。

本节使用简单的例子介绍其中最有用的控制结构。

下面这个例子展示了如何在模板中使用条件控制语句:

{% if user %}Hello,{{ user }}!
{% else %}Hello,Stranger!
{% endif %}

另一种常见需求是在模板中渲染一组元素。

下例展示了如何使用for 循环实现这一需求:

<ul>{% for comment in comments %}<li>{{ comment }}</li>{% endfor %}
</ul>

Jinja2还支持宏。宏类似于Python代码中的函数。

例如:

{% macro render_comment(comment) %}<li>{{ comment }}</li>
{% endmacro %}<ul>{% for comment in comments %}{{ render_comment(comment) }}{% endfor %}
</ul>

为了重复使用宏,我们还可以将其保存在单独的文件中,然后再需要使用的模板中导入:

{% import 'macro.html' as macros %}
<ul>{% for comment in comments %}{{ macros.render_comment(comment) }}{% endfor %}
</ul>

需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模块中,以避免重复:

{% include 'common.html' %}

另一种重复使用代码的强大方式是模板继承,它类似于Python代码中的类继承。

首先,创建一个名为base.html 的基模板:

<html>
<head>{% block head %}<title>{% block title %}{% endblock %} - My Application</title>{% endblock %}
</head>
<body>{% block body %}{% endblock %}
</body>
</html>

block 标签定义的元素可在衍生模板中修改。

在本例中,我们定义了名为 head、title和 block 的块。

注意,title 包含在 head 中。下面这个示例是基模板的衍生模板:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}{{ super() }}<style></style>
{% endblock %}
{% block body %}
<h1>Hello,World!</h1>
{% endblock %}

extends 指令声明了这个模板衍生自 base.html。

在 extends 指令之后,基模板中的3个块被重新定义,模板引擎会将其插入适当的位置。

注意新定义的 head 块,在基模板中其内容不是空的,所以使用 super() 获取原来的内容。

稍后会展示这些控制结构的具体用法,让你了解一些它们的工作原理。

3.2 使用Flask-Bootstrap 集成 Twitter Bootstrap

BootStrap(http://getbootstrap.com/)是 Twitter 开发的一个开源框架。

它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代Web浏览器。

Bootstrap 是客户端框架,因此不能直接涉及服务器。

服务器需要做的只是提供了引用Bootstrap层叠样式表(CSS)和JavaScript文件的HTML相应,并在HTML、CSS和JavaScript 代码中实例化所需组件。

这些操作最理想的执行场所就是模板。

要想在程序中集成Bootstrap,显然要对模板做所有必要的改动。

不过,更简单的方法是使用一个名为 Flask-Bootstrap 的Flask 扩展,简化集成的过程。

Flask-Bootstrap使用pip安装

pip install flask-bootstrap

Flask 扩展一般都在创建程序示例时初始化。

示例 3-4 是 Flask-Bootstrap的初始化方法。

示例 3-4 hello.py: 初始化 Flask-Bootstrap

from flask-bootstrap import Bootstrap#......

bootstrap = Bootstarp(app)

初始化Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。

这个模板利用Jinja2的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来引入Bootstrap的元素。

示例 3-5    templates/user.html  : 使用Flask-Bootstrap的模板

{% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block navbar %}
<div class="navbar navbar-inverse" role="navigation"><div class="container"><div class="navbar-header"><button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".navbar-collapse"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="/" >Flasky</a></div><div class="navbar-collapse collapse"><ul class="nav navbar-nav"><li><a href="/">Home</a></li></ul></div></div>
</div>
{% endblock %}{% block content %}
<div class="container"><div class="page-header"><h1>Hello,{{ name }}!</h1></div>
</div>
{% endblock%}

Jinja2 中的 extends 指令从 Flask-Bootstrap 中导入 bootstrap/base.html ,从而实现模板继承。

Flask-Bootstrap 中的基模板提供了一个网页框架,引入了 Bootstrap总的所有CSS和JavaStript文件。

基模板中定义了可在衍生模板中重定义的块。Block和endblock指令定义的块中的内容可添加到基模板中。

上面这个 user.html 模板定义了 3个块,分别名为 title、navbar和content。

这些块都是及模板提供的,可在衍生模板中重新定义。

title 块的作用很明显,其中的内容会出现在渲染后的HTML文档头部,放在<title>标签中。

navbar和content这两个块分别表示页面中的导航条和主体内容。

在这个模板中,vavbar 块使用Bootstrap 组件定义了一个简单的导航条。

content 块中有个<div>容器,其中包含一个页面头部。

之前版本的模板中的欢迎信息,现在就放在这个页面头部。

改动之后的程序,如图:

Flask-Bootstrap 的 base.html 模板还定义了很多其他块,都可以在衍生模板中使用。

Flask-Bootstrap基模板中定义的块

表3-2 Flask-Bootstrap 基模板中定义的块
块名 说明
doc  整个HTML文档
html_attribs <html>标签的属性
html <html>标签中的内容
head <head>标签中的内容
titlte <title>标签中的内容
metas 一组<meta>标签
styles 层叠样式表定义
body_attribs <body>标签的属性
body <body>标签中的内容
navbar 用户定义的导航条
content 用户定义的页面内容
scripts 文档底部的javaScript声明

上表中很多块都是Flask-Bootstrap自用的,如果直接重定义可能会导致一些问题。

例如,Bootsrap 所需的文件在styles 和 scripts 块中声明。

如果程序需要向已经有内容的块中添加新内容,必须使用Jinja2提供的super() 函数。

例如,若果要在衍生模板中添加新的JavaScript文件,需要这么定义scripts块。

{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}

3.3 自定义错误页面

如果在浏览器的地址栏中输入了不可用的路由,那么会显示一个状态码为 404 的错误页面。

现在这个错误页面太简陋、平庸,而且样式和使用了 Bootstrap 的页面不一致。

像常规路由一样,Flask允许程序使用基于模板的自定义页面。

最常见的错误代码有两个:

404 ,客户端请求未知页面或路由时显示;

500 , 有未处理的异常时显示。

为这两个错误代码指定自定义处理程序的方式如示例 3-6 所示。

示例3-6 hello.py :自定义错误页面

@app.errorhandler(404)
def page_not_found(e):return render_template('404.html'),404@app.errorhandler(500)
def internal_server_error(e):return render_template('500.html'),500

和视图函数一样,错误处理程序也会返回响应。

它们还返回与该错误对应的数数字状态码。

错误处理程序中引用的模板页需要编写。

这些模板应该和常规页面使用相同的布局,因此要有一个导航条和显示错误消息的页面头部。

编写这些模板最直观的方法是复制 templates/user.html ,分别创建 templates/404.html 和 templates/500.html ,然后把这两个文件中的页面为头部元素改为响应的错误消息。但这种方法会带来很多重复劳动。

Jinja2 的模板继承机制可以帮助我们解决这一问题。

Flask-Bootstrap 提供了一个具有页面基本布局的基模板,同样,程序可以定义一个具有完整页面布局的基模板,其中包含导航条,而页面内容则可留到衍生模板中定义。

示例 3-7 展示了 templates/base.html 的内容,这时一个继承自bootstrap/base.html 的新模板,其中定义了导航条。这个模板本身也可作为其他模板的基模板,例如 templates/user.html、templates/404.html 和 templates/500.html 。

示例 3-7 templates/base.html :包含导航条的程序基模板

{% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block navbar %}
<div class="navbar navbar-inverse" role="navigation"><div class="container"><div class="navbar-header"><button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".navbar-collapse"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="/" >Flasky</a></div><div class="navbar-collapse collapse"><ul class="nav navbar-nav"><li><a href="/">Home</a></li></ul></div></div>
</div>
{% endblock %}{% block content %}
<div class="container">{% block page_content %}{% endblock %}
</div>
{% endblock%}

这个模板的 content 块中只有一个 <div> 容器,其中包含了一个名为 page_content 的新的空块,该块中的内容由衍生模板定义。

现在,程序使用的模板继承自这个模板,而不是直接继承自 Flask-Bootstrap 的基模板。

通过集成 templates/base.html 模板编写自定义的404错误页面很简单,如示例 3-8 所示

示例3-8 templates/404.html : 使用模板继承机制自定义 404 错误页面

{% extends "base.html" %}{% block title %}Flasky - Page Not Found{% endblock %}{% block page_content %}
<div class="page-header"><h1>Not Found</h1>
</div>
{% endblock %}

错误页面在浏览器总显示效果:

templates/user.html 现在可以通过继承这个基模板来简化内容。如示例 3-9 所示。

示例 3-9   templates/user.html : 使用模板继承机制简化页面模板

{% extends "base.html" %}{% block title %}Flasky{% endblock%}{% block page_content %}
<div class="page-header"><h1>Hello,{{ name }}!</h1>
</div>
{% endblock %}

3.4 链接

任何具有多个路由的程序都需要可以连接不同页面的链接,例如导航条。

在模板中直接编写简单的路由的URL链接不难,但对于包含可变部分的动态路由,在模板中构建正确的URL就很困难。

而且,直接编写URL会对代码中定义的路由产生不必要的依赖关系。

如果重新定义路由,模板中的链接可能会失效。

为了避免这些问题,Flask 提供了  url_for() 辅助函数,它可以使用程序URL映射中保存的信息生成URL。

url_for() 函数最简单的用法是以视图函数名(或者 app.add_rul_route() 定义路由时使用的端点名)作为参数,返回对应的URL。

例如,在当前版本的 hello.py 程序中调用 url_for('index' )得到的结果是 / 。

调用 url_for('index',_external=True) 返回的则是绝对地址,在这个示例中是 http://localhost:5000/ 。

生成连接程序内不同路由的链接时,使用相对地址就足够了。

若要生成在浏览器之外使用的链接,则必须使用绝对地址,例如在电子邮件中发送的链接。

使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。

例如, url_for('user',name='john',_external=True)  返回的结果是 http://localhost:5000/user/john 。

传入 url_for() 的关键字参数不仅限于动态路由中的参数。

函数能将任何额外参数添加到查询字符串中。

例如, url_for('index',page=2) 返回的是 /?page=2 。

3.5 静态文件

Web程序不是仅由Python代码和模板组成。

大多数程序还会使用静态文件,例如HTML代码中引用的图片、JavaScript源码文件和CSS。

你可能还记得在第2章中检查hello.py 程序的URL映射时,其中有一个static路由。

这是因为对静态文件的引用被当成一个特殊的路由。即 /static/<filename>。

例如,调用  url_for('static',filename='css/styles.css',_external=True)

得到的结果是 http://localhost:5000/static/css/styles.css

默认设置下,Flask在程序根目录中名为static的文件夹中寻找静态文件。

如果需要,可在static文件夹中使用子文件夹存放文件。

服务器收到前面那个URL后,会生成以响应,包含文件系统中 static/css/static.css 文件的内容。

示例 3-10 展示了如何在程序的基模板中放置 favicon.ico 图标。这个图标会显示在浏览器的地址栏中。

示例 3-10 templates/base.html :定义收藏夹图标

{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static',filename='favicon.ico') }}"type="image/x-icon">
<link rel="icon" href="{{ url_for('static',filename='favicon.ico') }}" type="image/x-icon">
{% endblock %}

图标的声明会插入 head 块的末尾。

注意使用super() 保留基模板中定义的块的原始内容。

3.6 使用 Flask-Moment 本地化日期和时间

如果 Web 程序的用户来时世界各地,那么处理日期和时间可不是一个简单的任务。

服务器需要统一时间单位,这和用户所在的地理位置无关,所以一般使用协调时间时(Coordinated Universal Time ,UTC)。

不过用户看到UTC格式的时间会感到困惑,它们更希望看到当地时间,而且采用当地管用的格式。

要想在服务器上只使用UTC时间,一个优雅的解决方法是,把时间单位发送给Web浏览器,转换成当地时间,然后渲染。

Web 浏览器可以更好地完成这一任务,因为它能获取用户电脑中的时区和区域设置。

有一个使用JavaScript 开发的优秀客户端开源代码库,名为 moment.js (http://momentjs.com/),

它可以在浏览器中渲染日期和时间。

Flask-Moment 是一个Flask 程序扩展,能把moment.js 集成到Jinja2模板中。

Flask-Moment 可以使用 pip 安装:

pip  install flask-moment

这个扩展的初始化方法如示例3-11。

示例 3-11   hellp.py :初始化 Flask-Moment

from flask_moment import Moment
moment = Moment(app)

除了 moment.js ,Flask-Moment 还依赖jquery.js。

要在HTML文档的某个地方引入这两个库,可以直接引入,这样可以选择使用哪个版本,也可以使用扩展提供的辅助函数,从内容分发网络(Content Delivery ,CDN)中引入通过测试的版本。

Bootstrap 已经引入了 jquery.js,因此只需要引入 moment.js 即可。

示例 3-12 展示了如何在基模板的scripts 块中引入这个库。

示例 3-12   templates/base.html :引入Moment.js 库

{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

为了处理时间戳,Flask-Moment 向模板开放了moment 类。示例 3-13 中代码把变量current_time 传入模板进行熏染。

示例 3-13   hello.py:加入一个datetime变量

from datetime import datetime@app.route("/")
def index():                    return render_template('index.html',current_time=datetime.utcnow())

示例 3-14 展示了如何在模板中渲染 current_time。

示例 3-14   templates/index.html:使用 Flask-Moment 渲染时间戳

<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>

format('LLL') 根据客户端电脑中的时区和区域设置渲染日期和时间。

参数决定了渲染的方式,‘L’ 到 ‘LLL’ 分贝对应不同的复杂度。

format() 函数还可接受自定义的格式说明符。

第二行中的 fromNow() 渲染相对时间戳,而且会随着时间的推移自动刷新显示的时间。

这个时间戳最开始显示为 “a few seconds ago”,但指定 refresh 参数后,其内容会随着时间的推移个更新。

如果一直待在这个页面,几分钟后,会看到显示的文本变成 "a mimute age" "2 minutes age"等。

Flask-Moment 实现了 moment.js中的 format()fromNow()calendar()valueOf()unix() 方法。

你可查阅文档(http://momentjs.com/docs/#/displaying/)学习moment.js提供的全部格式化选项。

Flask-Moment 假定服务器端程序处理的时间戳是“纯正的”datetime对象,且使用UTC表示。

关于纯正和细致的日期和时间对象的说明,请阅读标准库中datetime包的文档(https://docs.python.org/3/library/datetime.html)

( 纯正的时间戳,英文为 navie time,指不包含时区的时间戳;
  细致的时间戳,英文为 aware time,指包含时区的时间戳)

Flask-Moment 渲染的时间戳可实现多种语言的本地化。

语言可在模板中选择,把语言代码传给 lang() 函数即可:

{{ moment.lang('es') }}

使用本章介绍的技术,你应该能为程序编写出现代化且用户友好的网页。

下一章将介绍本章没有涉及的一个模板功能,即如果通过Web 表单和用户交互。

转载于:https://www.cnblogs.com/doitjust/p/9874129.html

基于Python的Web应用开发实战——3 模板相关推荐

  1. 学习《Flask Web开发:基于Python的Web应用开发实战》分享

    学习<Flask Web开发:基于Python的Web应用开发实战>分享一直在说学习Python,对同事,对朋友,都说我正在学习Python,这无形给自己一定的压力,促使自己要去学习,进步 ...

  2. 《FlaskWeb开发:基于Python的Web应用开发实战》笔记

    开源库的cdn加速 可以在这里直接搜索复制script链接 https://www.bootcdn.cn/ requirements.txt文件的生成与使用 生成requirements文件:$ pi ...

  3. 《Flask Web开发:基于Python的Web应用开发实战》笔记(原创)

    内容提要 在学习"狗书"<Flask Web开发:基于Python的Web应用开发实战>的过程中,一直遇到各种各样的坑.该书的第一部分是"Flask简介&qu ...

  4. Flask Web开发:基于Python的Web应用开发实战

    <Flask Web开发:基于Python的Web应用开发实战> 虽然简单的网站(Flask+Python+SAE)已经上线,但只是入门.开发大型网站,系统地学习一遍还是有必要的. 201 ...

  5. flask web开发:基于python的web应用开发实战_在知乎上学 Python Web 开发篇

    通知: 1. 最近我们将进行2期学习小组,面向完全零基础的Python入门学习小组已经开始,第一次任务的讨论将于明晚(15号)进行,现在上车还来得及 2. 另有一期数据可视化小组将于年前启动,第一次讨 ...

  6. 基于python的网站开发-FlaskWeb开发:基于Python的Web应用开发实战 pdf下载

    这大概是入门Flask最最经典的教材了.可是我依然看得很吃力,我的自控力啊啊~到哪里去了 讲的挺全面挺系统 有的地方需要硬肯 不过好在指明了方向 比较贴近现在流行的开发模式 这两天写了一个小博客应用 ...

  7. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构 前言 学习Python也有一个半月时间了,学到现在感觉还是 ...

  8. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(下)

    目录 前言 第8章 用户认证 第9章 用户角色 第10章 用户资料 第11章 博客文章 第12章 关注者 第13章 用户评论 第14章 应用编程接口   前言 第1章-第7章学习实践记录请参见:< ...

  9. 基于python的web应用开发-添加关注者

    社交web允许用户之间相互联系. 例如: 关注者.好友.联系人.联络人或伙伴. 记录两个用户之间的定向联系,在数据库查询中也要使用这种联系. 一.论数据库关系 一对多关系 数据库使用关系建立记录之间的 ...

最新文章

  1. MediaWiki 1.19.2 发布 - 开源 Wiki 系统
  2. 远程登录的机器不是域控制器的方法
  3. 【Java】7.3 基本类 7.4 Java 8 的日期、时间类
  4. 若依前后端分离版数据库已经存在的字典添加一条后刷新没作用,必须清除Redis缓存
  5. PPT 下载 | 纷享销客刘晨:客户生命周期服务设计
  6. 使用 Scrum开发太阳能汽车
  7. make clean
  8. qtreewidgetitem 选中背景颜色_列表式报表阶梯背景色效果
  9. 20190823 尚硅谷MySQL核心技术
  10. 自考 《计算机网络原理04741》真题解析
  11. 洛谷-UVA12676 Inverting Huffman(反转树)
  12. 谷歌(chrome)恐龙小游戏外挂
  13. 安卓版本与adb的问题
  14. 论文引用部分是否需要查重?
  15. JIAR 使用笔记 - 素材
  16. 没有这个路径C:\Program Files\Microsoft Office\root\Office16怎么办
  17. 这个 Go 开发的网络抓包工具,不仅好用还支持ES检索
  18. oracle 英文转数字,数字转换成英文
  19. 结合深度学习检测心脏 智能戒指体积小又准确
  20. 腾讯 阿里 华为的岗位薪资情况概述

热门文章

  1. 用python制作生日蛋糕图片大全_Python 制作微信全家福,你就是朋友圈最亮的仔!...
  2. halt ,poweroff和shutdown 的区别
  3. 浏览器F12控制台简述Network
  4. Smith Chart - for myself
  5. Cocos Creator发布H5游戏,做项目构建流程定制
  6. PG用户default privileges授权不生效?
  7. C语言试题151之求 0到7 所能组成的奇数个数。
  8. 微步星辰的逆袭,专访微步星辰合伙人齐成岳
  9. Wi-Fi MAC 地址随机化与人群监控
  10. 电脑公司纯净版GHOST_XP_SP3_V12