Web应用程序和框架

../_images/34309496175_b82d104282_k_d.jpg

Python是一种功能强大的脚本语言,适用于快速原型和大型项目,在Web应用程序开发中得到了广泛的应用。

上下文

WSGI

Web服务器网关接口(简称“wsgi”)是Web服务器和PythonWeb应用程序框架之间的标准接口。通过标准化Web服务器和python Web框架之间的行为和通信,wsgi使编写可移植的python Web代码成为可能,这些代码可以部署在 WSGI-compliant web server .WSGi记录在 PEP 3333 .

框架

一般来说,Web框架由一组库和一个主处理程序组成,您可以在其中构建自定义代码来实现Web应用程序(即交互网站)。大多数Web框架都包含模式和实用程序,以至少完成以下任务:

路径选择

将传入的HTTP请求与要调用的特定python代码段匹配

请求和响应对象

封装从用户浏览器接收或发送到用户浏览器的信息

模板引擎

允许将实现应用程序逻辑的Python代码与它生成的HTML(或其他)输出分离

开发Web服务器

在开发计算机上运行HTTP服务器以实现快速开发;通常在更新文件时自动重新加载服务器端代码

Django

Django 是一个“包含电池”的Web应用程序框架,是创建面向内容的网站的最佳选择。通过提供许多现成的实用程序和模式,Django旨在使快速构建复杂的、数据库支持的Web应用程序成为可能,同时鼓励使用它编写代码的最佳实践。

Django有一个庞大而活跃的社区,以及许多预建的 re-usable modules 可以按原样合并到新项目中,也可以根据需要进行定制。

有一年一度的django会议 in the United StatesEuropeAustralia .

现在大多数新的python web应用程序都是用django构建的。

Flask

Flask 是Python的“微框架”,是构建小型应用程序、API和Web服务的最佳选择。

用flask构建应用程序很像编写标准的python模块,除了一些函数有附加的路由。它真的很漂亮。

Flask实现了Web应用程序框架中最常用的核心组件,比如URL路由、请求和响应对象以及模板,而不是提供您可能需要的一切。

如果您使用烧瓶,则由您自己为您的应用程序选择其他组件(如果有的话)。例如,数据库访问或表单生成和验证不是flask的内置功能。

这很好,因为许多Web应用程序不需要这些功能。对于那些这样做的人,有很多 Extensions 可以满足您的需求。或者,你可以很容易地使用任何你想要的类库!

flask是任何不适合django的python web应用程序的默认选择。

Falcon

Falcon 当您的目标是构建快速且可扩展的RESTfulAPI微服务时,这是一个不错的选择。

它是一个可靠的、高性能的python web框架,用于构建大规模的应用程序后端和微服务。Falcon鼓励将URI映射到资源的其余体系结构风格,在保持高效的同时尽可能少地执行操作。

Falcon强调了四个主要重点:速度、可靠性、灵活性和可调试性。它通过“响应程序”实现HTTP,例如 on_get()on_put() 等等。这些响应者接收直观的请求和响应对象。

Tornado

Tornado 是一个针对Python的异步Web框架,它有自己的事件循环。例如,这允许它以本机方式支持WebSockets。众所周知,编写良好的Tornado应用程序具有出色的性能特征。

我不建议使用龙卷风,除非你认为你需要它。

Pyramid

Pyramid 是一个非常灵活的框架,重点关注模块化。它内置了少量的库(“电池”),并鼓励用户扩展其基本功能。提供的一组cookiecutter模板有助于为用户制定新的项目决策。它为Python基础架构最重要的部分之一提供了动力 PyPI .

与Django和Flask不同,金字塔没有很大的用户基础。它是一个功能强大的框架,但对于当今的新的python web应用程序来说不是一个非常流行的选择。

Masonite

Masonite 是一个以开发人员为中心的现代网络框架,包括电池。

Masonite框架遵循MVC(Model View Controller)架构模式,深受Rails和Laravel等框架的启发,因此,如果您是从Ruby或PHP背景进入Python的,那么您会感到宾至如归!

Masonite提供了很多现成的功能,包括一个强大的IOC容器,带有自动解析依赖项注入、手工命令行工具和演说家活动记录样式ORM。

Masonite非常适合初学者或经验丰富的开发人员,从安装到部署都要努力做到快速简单。试一试,你就会坠入爱河。

快速API

FastAPI 是一个用Python3.6+构建API的现代Web框架。

它有很高的性能,因为它是基于 StarlettePydantic .

FastAPI利用函数参数中的标准python类型声明来声明请求参数和主体、执行数据转换(序列化、解析)、数据验证和自动API文档 OpenAPI 3 (包括 JSON模式

它包括用于安全和身份验证的工具和实用程序(包括带有JWT令牌的OAuth2)、依赖项注入系统、交互式API文档的自动生成以及其他功能。

网络服务器

Nginx

Nginx (发音为“engine-x”)是一个Web服务器和HTTP、SMTP和其他协议的反向代理。它以其高性能、相对简单以及与许多应用服务器(如wsgi服务器)的兼容性而闻名。它还包括诸如负载平衡、基本身份验证、流式处理等方便的功能。为了服务于高负载的网站,nginx逐渐变得相当流行。

WSGi服务器

独立的WSGi服务器通常比传统的Web服务器使用更少的资源,并提供最高的性能 1.

Gunicorn

Gunicorn (绿色独角兽)是一个纯python wsgi服务器,用于服务python应用程序。与其他的python web服务器不同,它有一个深思熟虑的用户界面,并且非常容易使用和配置。

对于配置,Gunicorn具有健全和合理的默认值。然而,一些其他的服务器,如UWSGI,是非常可定制的,因此,更难以有效地使用。

Gunicorn是当今新的PythonWeb应用程序的推荐选择。

Waitress

Waitress 是一个纯粹的python wsgi服务器,它声称“非常可接受的性能”。它的文档不是很详细,但它提供了一些Gunicorn没有的好功能(例如HTTP请求缓冲)。

服务生在python web开发社区中越来越受欢迎。

UWSGI

uWSGI 是用于生成托管服务的完整堆栈。除了流程管理、流程监控和其他功能外,Uwsgi还充当各种编程语言和协议(包括python和wsgi)的应用服务器。Uwsgi既可以作为独立的Web路由器运行,也可以在完整的Web服务器(如nginx或apache)后面运行。在后一种情况下,Web服务器可以通过 uwsgi protocol .Uwsgi的Web服务器支持允许动态配置python、传递环境变量和进一步的调优。有关详细信息,请参阅 uWSGI magic variables .

我不建议使用Uwsgi,除非你知道你为什么需要它。

服务器最佳实践

目前大多数自托管的Python应用程序都托管在wsgi服务器上,例如 Gunicorn 直接或在轻量级Web服务器(如 nginx .

wsgi服务器为python应用程序提供服务,而web服务器则处理更适合它的任务,例如静态文件服务、请求路由、ddos保护和基本身份验证。

托管

平台即服务(paas)是一种云计算基础设施,它抽象和管理网络应用程序的基础设施、路由和扩展。当使用PaaS时,应用程序开发人员可以专注于编写应用程序代码,而不需要关注部署细节。

Heroku

Heroku 为python 2.7–3.5应用程序提供一流的支持。

Heroku支持所有类型的PythonWeb应用程序、服务器和框架。可以免费在Heroku上开发应用程序。一旦您的应用程序准备好生产,您可以升级到业余爱好或专业应用程序。

Heroku坚持 detailed articles 关于使用Python和Heroku,以及 step-by-step instructions 关于如何设置第一个应用程序。

Heroku是当今部署PythonWeb应用程序的推荐PaaS。

Eldarion

Eldarion (以前称为刚铎)是一个由Kubernetes、Coreos和Docker提供动力的PaaS。它们支持任何WSGi应用程序,并有部署指南 Django projects .

模板法

大多数WSGi应用程序都响应HTTP请求,以HTML或其他标记语言提供内容。与直接从Python生成文本内容不同,关注点分离的概念建议我们使用模板。模板引擎管理一套模板文件,采用层次结构和包含系统,以避免不必要的重复,并负责呈现(生成)实际内容,用应用程序生成的动态内容填充模板的静态内容。

由于模板文件有时由设计师或前端开发人员编写,因此很难处理日益复杂的问题。

一些一般的好实践应用于将动态内容传递给模板引擎的应用程序部分,以及模板本身。

  • 模板文件只应传递呈现模板所需的动态内容。避免“以防万一”传递附加内容的诱惑:在需要时添加缺少的变量比稍后删除可能未使用的变量更容易。

  • 许多模板引擎允许在模板本身中使用复杂的语句或赋值,许多模板引擎允许在模板中计算一些Python代码。这种便利性会导致不受控制的复杂性增加,并且常常使查找错误变得更加困难。

  • 通常需要将JavaScript模板与HTML模板混合使用。一个明智的设计方法是隔离HTML模板将一些变量内容传递给JavaScript代码的部分。

Jinja2

Jinja2 是一个非常受欢迎的模板引擎。

它使用基于文本的模板语言,因此可以用于生成任何类型的标记,而不仅仅是HTML。它允许定制过滤器、标签、测试和全局参数。它比Django的模板系统有很多改进。

以下是jinja2中的一些重要HTML标记:

{# This is a comment #}

{# The next tag is a variable output: #}
{{title}}

{# Tag for a block, can be replaced through inheritance with other html code #}
{% block head %}
<h1>This is the head!</h1>
{% endblock %}

{# Output of an array as an iteration #}
{% for item in list %}
<li>{{ item }}</li>
{% endfor %}

下面的列表是一个结合了Tornado Web服务器的网站示例。龙卷风的使用并不复杂。

# import Jinja2
from jinja2 import Environment, FileSystemLoader

# import Tornado
import tornado.ioloop
import tornado.web

# Load template file templates/site.html
TEMPLATE_FILE = "site.html"
templateLoader = FileSystemLoader( searchpath="templates/" )
templateEnv = Environment( loader=templateLoader )
template = templateEnv.get_template(TEMPLATE_FILE)

# List for famous movie rendering
movie_list = [[1,"The Hitchhiker's Guide to the Galaxy"],[2,"Back to future"],[3,"Matrix"]]

# template.render() returns a string which contains the rendered html
html_output = template.render(list=movie_list,
                        title="Here is my favorite movie list")

# Handler for main page
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        # Returns rendered template string to the browser request
        self.write(html_output)

# Assign handler to the server root  (127.0.0.1:PORT/)
application = tornado.web.Application([
    (r"/", MainHandler),
])
PORT=8884
if __name__ == "__main__":
    # Setup the server
    application.listen(PORT)
    tornado.ioloop.IOLoop.instance().start()

这个 base.html 文件可以用作所有网站页面的基础,例如在内容块中实现的网站页面。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{{title}} - My Webpage</title>
</head>
<body>
<div id="content">
    {# In the next line the content from the site.html template will be added #}
    {% block content %}{% endblock %}
</div>
<div id="footer">
    {% block footer %}
    &copy; Copyright 2013 by <a href="http://domain.invalid/">you</a>.
    {% endblock %}
</div>
</body>

下一个列表是我们的网站页面 (site.html )加载在python应用程序中,扩展 base.html .内容块将自动设置为 base.html 页。

{% extends "base.html" %}
{% block content %}
    <p class="important">
    <div id="content">
        <h2>{{title}}</h2>
        <p>{{ list_title }}</p>
        <ul>
             {% for item in list %}
             <li>{{ item[0]}} :  {{ item[1]}}</li>
             {% endfor %}
        </ul>
    </div>
    </p>
{% endblock %}

jinja2是新的python web应用程序的推荐模板库。

Chameleon

Chameleon 页面模板是HTML/XML模板引擎实现的 Template Attribute Language (TAL)TAL Expression Syntax (TALES)Macro Expansion TAL (Metal) 句法。

变色龙可用于python 2.5及更高版本(包括3.x和pypy),通常用于 Pyramid Framework .

页面模板在文档结构中添加特殊元素属性和文本标记。使用一组简单的语言结构,可以控制文档流、元素重复、文本替换和翻译。由于基于属性的语法,未引用的页面模板是有效的HTML,可以在浏览器中查看,甚至可以在所见即所得编辑器中编辑。这可以使与设计人员的往返协作以及在浏览器中使用静态文件进行原型设计变得更容易。

基本的TAL语言非常简单,可以通过一个例子来理解:

<html>
  <body>
  <h1>Hello, <span tal:replace="context.name">World</span>!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           <span tal:replace="row.capitalize()" /> <span tal:replace="col" />
        </td>
      </tr>
    </table>
  </body>
</html>

这个 <span tal:replace="expression" /> 文本插入模式非常常见,如果您不需要在未引用的模板中使用严格的有效性,可以用更简洁易读的语法替换它,该语法使用模式 ${{expression}} 如下:

<html>
  <body>
    <h1>Hello, ${world}!</h1>
    <table>
      <tr tal:repeat="row 'apple', 'banana', 'pineapple'">
        <td tal:repeat="col 'juice', 'muffin', 'pie'">
           ${row.capitalize()} ${col}
        </td>
      </tr>
    </table>
  </body>
</html>

但要记住的是 <span tal:replace="expression">Default Text</span> 语法还允许在未引用的模板中使用默认内容。

变色龙来自金字塔世界,并没有被广泛使用。

Mako

Mako 是一种模板语言,可编译为Python以获得最佳性能。它的语法和API是从其他模板语言(如django和jinja2模板)的最佳部分借用的。它是包含在 Pylons and Pyramid Web框架。

Mako中的示例模板如下:

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>

<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

要呈现非常基本的模板,可以执行以下操作:

from mako.template import Template
print(Template("hello ${data}!").render(data="world"))

Mako在PythonWeb社区中备受尊敬。

工具书类

1

Benchmark of Python WSGI Servers