Web2py - 快速指南


Web2py - 简介

web2py被定义为一个免费的开源 Web 框架,用于敏捷开发,涉及数据库驱动的 Web 应用程序;它是用 Python 编写的,并且可以用 Python 编程。它是一个全栈框架;它由所有必要的组件组成,开发人员需要构建一个功能齐全的 Web 应用程序。

web2py框架遵循模型-视图-控制器模式来运行 Web 应用程序,这与传统模式不同。

  • 模型是应用程序的一部分,包含数据逻辑。模型中的对象用于从数据库中检索和存储数据。

  • 视图是应用程序的一部分,有助于向最终用户呈现数据显示。数据的显示是从模型中获取的。

  • 控制器是应用程序的一部分,负责处理用户交互。控制器可以从视图读取数据、控制用户输入并将输入数据发送到特定模型。

Web2py 设备
  • web2py有一个内置功能来管理 cookie 和会话。提交事务(就SQL而言)后,会话也同时被存储。

  • web2py能够在完成某些操作后按计划的时间间隔运行任务。这可以通过CRON来实现。

web2py – 工作流程

看看下面给出的工作流程图。

工作流程

工作流程图如下所述。

  • Models 、ViewsController组件组成了用户 web2py 应用程序

  • 多个应用程序可以托管在同一个 web2py 实例中。

  • 浏览器向服务器发送 HTTP 请求,服务器与ModelControllerView交互以获取必要的输出。

  • 箭头表示与数据库引擎的通信。数据库查询可以用原始 SQL 或使用 web2py 数据库抽象层(将在后续章节中讨论)编写,以便web2py应用程序代码独立于任何数据库引擎。

  • Model与数据库建立数据库连接并与Controller交互。另一方面,控制器视图交互以呈现数据的显示。

  • 调度程序将HTTP 响应中给出的请求 URL 映射到控制器中的函数调用。函数的输出可以是字符串或哈希表。

  • 数据由View呈现。如果用户请求 HTML 页面(默认),数据将呈现为 HTML 页面。如果用户请求 XML 中的同一页面,web2py 会尝试查找可以呈现 XML 中的字典的视图。

  • web2py支持的协议包括HTML、XML、JSON、RSS、CSV和RTF。

模型-视图-控制器

web2py 的模型-视图-控制器表示如下 -

模型

"db.py" is the model:
db = DAL('sqlite://storage.sqlite')
db.define_table(employee, Field('name'), Field(‘phone’))

模型包括应用程序数据的逻辑。它连接到数据库,如上图所示。考虑正在使用 SQLite 并将其存储在storage.sqlite文件中,并将表定义为员工。如果该表不存在,web2py 会通过创建相应的表来提供帮助。

控制器

程序“default.py”控制器

def employees():
   grid = SQLFORM.grid(db.contact, user_signature = False)
   return locals()

web2py中,URL 映射有助于访问函数和模块。对于上面的示例,控制器包含一个称为员工的函数(或“操作”)。

控制器执行的操作返回一个字符串或一个 Python 字典,它是键和值的组合,包括一组本地变量。

看法

“default/contacts.html”视图

{{extend 'layout.html'}}
<h1>Manage My Employees</h1>
{{=grid}}

对于给定的示例,视图在执行关联的控制器函数后显示输出。

这个View的目的是渲染字典中的变量,字典是HTML形式的。View文件是用 HTML 编写的,但它{{ 和 }}分隔符的帮助下嵌入了 Python 代码。

嵌入到 HTML 中的代码由字典中的 Python 代码组成。

从 web2py 开始

web2py提供适用于所有主要操作系统(如 Windows、UNIX 和 Mac OS X)的二进制包。

安装 web2py 很容易,因为 -

  • 它包含 Python 解释器,因此您无需预先安装它。还有一个可在所有操作系统上运行的源代码版本。

  • 以下链接包含web2py的二进制包,可根据用户的需要下载 - www.web2py.com

  • 与其他框架不同, web2py框架不需要预先安装。用户需要下载zip文件并根据操作系统要求解压。

  • web2py框架是用Python编写的,Python是一种完整的动态语言不需要任何编译或复杂的安装即可运行。

  • 它与其他编程语言(例如 Java 或 .net)一样使用虚拟机,并且可以透明地对开发人员编写的源代码进行字节编译。

操作系统 命令
Unix 和 Linux(源代码发行版) 蟒蛇 web2py.py
OS X(二进制发行版) 打开 web2py.app
Windows(二进制 web2py 发行版) web2py.exe
Windows(源 web2py 发行版) c:/Python27/python.exe web2py.py

Web2py - Python 语言

Python可以被定义为面向对象和交互式语言的结合。它是一个开源软件。Guido van Rossum 在 20 世纪 80 年代末期构思了 Python。

Python是一种类似于PERL(实用提取和报告语言)的语言,因其语法清晰和可读性而受到欢迎。

Python 的主要显着特征如下:

  • 据说Python相对容易学习和移植。它的语句可以在许多操作系统中轻松解释,包括基于 UNIX 的系统、Mac OSMS-DOSOS/2和各种版本的 Windows。

  • Python 可移植到所有主要操作系统。它使用易于理解的语法,使程序对用户友好。

  • 它配备了一个支持许多任务的大型标准库。

脚本语言

从上图可以清楚地看出Python是脚本语言和编程语言的结合体。它们在另一个程序(如脚本语言)中被解释。

Python 的版本

Python 具有三种生产质量的实现,分别称为 CPython、Jython 和 IronPython。这些也称为 Python 版本。

  • 经典 Python又名CPython是一个编译器、解释器,由内置和可选的扩展模块组成,以标准 C 语言实现。

  • Jython是 Java 虚拟机 (JVM) 的 Python 实现。

  • IronPython由 Microsoft 设计,其中包含公共语言运行时 (CLR)。它通常被称为.NET

启动

任何操作系统中的基本 Python 程序都以标头开头。程序以.py扩展名存储,并使用Python命令来运行程序。

例如,python_rstprogram.py将为您提供所需的输出。如果存在的话,它也会产生错误。

Python 使用缩进来分隔代码块。一个块以以冒号结尾的行开始,并以类似的方式继续所有与下一行具有相似或更高缩进的行。

# Basic program in Python
print "Welcome to Python!\n"

程序的输出将是 -

Welcome to Python!

缩进

Python 中程序的缩进非常重要。对于 Python 初学者来说,对于 Python 的缩进规则存在一些偏见和误解。

所有程序员的经验法则是 -

“空格在 Python 源代码中很重要。”

前导空白(包括 Python 逻辑行开头的空格和制表符)计算行的缩进级别。

笔记

  • 缩进级别还决定了语句的分组。

  • 通常使用四个空格(即制表符)来表示每一级缩进。

  • 最好不要将制表符与空格混用,否则会导致看不见的混乱。

如果缺少缩进,Python 也会生成编译时错误。

IndentationError: expected an indented block

控制流语句

Python 程序的控制流由条件语句、循环和函数调用来调节。

  • If语句在指定条件下与 else 和 elif(else-if组合)一起执行代码块。

  • For语句迭代对象,将每个元素捕获到局部变量以供附加块使用

  • While语句在条件为True 的情况下执行代码块。

  • With语句上下文管理器中的代码块括起来。它已被添加为try/finally语句的更具可读性的替代方案。

# If statement in Python
   x = int(raw_input("Please enter an integer: ")) #Taking input from the user
if x<0:
   print "1 - Got a negative expression value"
   print x
else:
   print "1 - Got a positive expression value"
   print x
print "Good bye!"

输出

sh-4.3$ python main.py
Please enter an integer: 4
1 - Got a positive expression value
4
Good bye!

功能

典型的 Python 程序中的语句以称为“函数”的特定格式进行组织和分组。函数是一组根据请求执行操作的语句。Python 提供了许多内置函数,并允许程序员定义它们的函数自己的功能。

在 Python 中,函数是像编程语言中的其他对象一样处理的值。

def语句是定义函数的最常见方法。def是一个单子句复合语句,语法如下 -

def function-name (parameters):statement(s)

以下示例演示了生成器函数。它可以用作可迭代对象,以类似的方式创建其对象。

def demo ():
   for i in range(5):
      yield (i*i)
	
for j in demo():
   print j

输出

sh-4.3$ python main.py
0
1
4
9
16

特殊属性、方法和运算符

类的以双下划线开头的属性、方法和运算符通常在Behave上是私有的。其中一些是保留关键字,其中包含特殊含义。

下面列出了其中三个 -

  • __长度__

  • __获取项目__

  • __设置项目__

其他特殊运算符包括 __getattr__ 和 __setattr__,它们定义类的getset属性。

文件输入/输出功能

Python 包含打开和关闭特定文件的功能。这可以借助open()write()close()函数来实现。

有助于文件输入和输出的命令如下 -

先生编号 命令与功能
1

打开()

它有助于打开文件或文档

2

写()

它有助于在文件或文档中写入字符串

3

读()

它有助于读取现有文件中的内容

4

关闭()

该方法关闭文件对象。

例子

考虑一个名为“demo.txt”的文件,该文件已经存在并带有文本“这是一个演示文件”。

#!/usr/bin/python
# Open a file
fo = open("demo.txt", "wb")
fo.write( "Insering new line \n");
# Close opend file
fo.close()

打开文件后可用的字符串为 -

This is a demo file
Inserting a new line

Web2py - 框架概述

web2py 是一个全栈 Web 框架,开发人员可以使用它来完整开发 Web 应用程序。它包括 SQL 数据库集成和用于设计程序的多线程 Web 服务器。

用于设计用户程序的 Web 界面

一旦按照操作系统执行命令,web2py 将显示一个启动窗口,然后显示一个 GUI 小部件,要求用户选择 -

  • 一次性管理员密码,
  • 用于 Web 服务器的网络接口的 IP 地址,
  • 以及服务请求的端口号。

管理员拥有添加和编辑任何新 Web 应用程序的所有权限。

默认情况下,web2py 在127.0.0.1:8000(本地主机上的端口 8000)上运行其 Web 服务器,但用户可以根据要求在任何可用的 IP 地址和端口上运行它。

web2py GUI 小部件将显示如下所示。

图形用户界面小工具

该密码用于管理界面中以进行新模块中的任何更改。

用户设置管理密码后,web2py 在具有以下 URL 的页面启动 Web 浏览器 - http://127.0.0.1:8000/

框架的欢迎页面将显示如下所示。

框架

在 web2py 中设计一个基本程序

启动 web2py 应用程序后,使用上述 URL,我们可以使用管理界面创建新模块,例如“helloWorld”

管理界面将要求输入密码以进行身份​​验证,因为管理员拥有添加和编辑任何新 Web 应用程序的所有权限。

Web2py 应用程序

上面给出的快照包括页面详细信息,其中列出了所有已安装的 web2py 应用程序并允许管理员管理它们。默认情况下,web2py 框架附带三个应用程序。他们是 -

  • 用户当前正在实施的管理应用程序。

  • 一个示例应用程序,带有在线交互式文档和 web2py 官方网站的实例。

  • 一个受欢迎的应用程序。它包括任何其他 web2py 应用程序的基本模板。它也称为脚手架应用。该应用程序还在启动时欢迎用户。

让新应用程序的名称为“helloWorld”

一旦创建了新应用程序,用户就会被重定向到包含相应应用程序的视图、模型和控制器的页面。

编辑申请

用户可以通过提及以下 URL 来查看新创建的应用程序 - http://127.0.0.1:8000/helloWorld

默认情况下,用户点击上述 URL 即可查看以下屏幕。

为了打印给定 Web 应用程序“helloWorld”的消息,在default.py控制器中进行更改。

Web应用程序

名为“index”的函数是返回值并显示必要输出的默认函数。如上所述,字符串“Hello World- 欢迎来到我的第一个 Web 应用程序”用作返回值,它在屏幕上显示输出。

输出显示如下 -

输出

回发

验证表单输入的机制非常常见,但不被认为是一种很好的编程实践。每次都会对输入进行验证,这对验证来说是一个负担。

web2py 中更好的模式是将表单提交到生成表单的同一操作。这种机制被称为“postback”,这是web2py的主要特征。简而言之,就是在postback中实现了自提交。

def first():
   if request.vars.visitor_name: #if visitor name exists
      session.visitor_name = request.vars.visitor_name
      redirect(URL('second'))#postback is implemented
   return dict()

增删改查应用

web2py 包括执行创建、检索、更新和删除功能的应用程序。CRUD循环描述了数据库的基本功能,它是持久的。

所有应用程序逻辑都编写在模型中,由控制器检索并借助视图向用户显示。

应用管理

对于 PHP,应用程序服务器包括phpmyadmin下所有数据库的列表。类似地,web2py 提供了一个用于管理、创建和删除表或数据库的界面,称为“appadmin”。

在实现表背后的逻辑之前,需要创建数据库及其关联表。

访问appadmin 的URL -

http://127.0.0.1:8000/applicationname/appadmin

点击 URL 后,用户将获得与给定应用程序关联的表列表。

表格列表

该接口不打算公开。它旨在轻松访问数据库。它由两个文件组成,即控制器“appadmin.py”和视图“appadmin.html”

它一次最多可以对 100 条记录进行分页。“appadmin”的用法将在后续章节中讨论。

Web2py - 核心

命令行选项

我们在上一章中学习了如何使用 GUI 小部件启动 web2py 服务器。

可以通过从命令行提示符启动服务器来跳过此小部件。

python web2py.py -a '你的密码' -i 127.0.0.1 -p 8000

每当 web2py 服务器启动时,它都会创建一个文件“ parameters_8000.py ”,其中所有密码都以哈希形式存储。

为了额外的安全目的,可以使用以下命令行 -

python web2py.py -a '<recycle>' -i 127.0.0.1 -p 8000

对于上述场景,web2py 重用存储在“ parameters_8000.py ”中的哈希密码。

如果文件“ parameters_8000.py ”被意外删除或由于其他原因,则 web2py 中基于 Web 的管理界面将被禁用。

URL 映射/调度

web2py 的功能基于 model-view-controller,它以特定的形式映射 URL - http://127.0.0.1:8000/a/d/f.html

它会进行路由,直到控制器d.py中提到的函数“f()”位于名为“a”的应用程序下。如果应用程序中不存在控制器,则 web2py 使用名为“default.py”的默认控制器。

如果 URL 中给出的函数不存在,则使用名为init()的默认函数。URL 的工作原理如下图所示。

函数初始化

URL 的扩展名.html是可选的。扩展决定了呈现控制器中定义的函数的输出的View的扩展。相同的内容以多种格式提供,即 html、xml、json、rss 等。

根据函数传递请求,函数接受参数并向用户提供适当的输出。它是控制器,与应用程序的模型和视图交互,根据用户的需要提供输出。

web2py – 工作流程

下面讨论 web2py 的工作流程 -

  • Web 服务器在自己的线程中同时管理每个 HTTP 请求。

  • HTTP 请求标头被解析并传递给调度程序。

  • Dispatcher 管理应用程序请求并将PATH_INFO映射到函数调用的 URL 中。每个函数调用都在 URL 中表示。

  • 对静态文件夹中包含的文件的所有请求都直接管理,大文件将流式传输到客户端。

  • 对除静态文件之外的任何内容的请求都会映射到操作中。

  • 如果请求标头包含应用程序的会话 cookie,则检索会话对象;否则,将创建一个会话 ID。

  • 如果操作返回字符串值,则该值将返回给客户端。

  • 如果该操作返回一个可迭代对象,则它用于循环并将数据流式传输到客户端。

条件模型

在上一章中,我们了解了控制器的功能。web2py 在其每个应用程序中使用模型、视图和控制器。因此,了解Model的功能也是有必要的。

与任何其他 MVC 应用程序不同,web2py 中的模型被视为有条件的。子文件夹中的模型根据其控制器的使用情况执行。这可以通过以下示例来证明 -

考虑 URL - http://127.0.0.1:8000/a/d/f.html

在本例中,“a”是应用程序的名称,“d”是控制器的名称,f()是与控制器关联的函数。将执行的模型列表如下 -

applications/a/models/*.py
applications/a/models/d/*.py
applications/a/models/d/f/*.py

图书馆

web2py 包含库,这些库作为对象公开给所有应用程序。这些对象在名为“gluon”的目录下的核心文件中定义。

许多模块(例如 DAL 模板)没有依赖关系,可以在 web2py 框架之外实现。它还维护被认为是良好实践的单元测试。

应用领域

web2py 应用程序如下图所示。

图表形式

在 web2py 中开发的应用程序由以下部分组成 -

  • 模型- 表示数据和数据库表。

  • 控制器- 描述应用程序逻辑和工作流程。

  • 视图- 帮助渲染数据的显示。

  • 语言- 描述如何将应用程序中的字符串翻译成各种支持的语言。

  • 静态文件- 不需要处理(例如图像、CSS 样式表等)。

  • 关于自述文件- 项目的详细信息。

  • 错误- 存储应用程序生成的错误报告。

  • 会话- 存储与每个特定用户相关的信息。

  • 数据库- 存储 SQLite 数据库和附加表信息。

  • 缓存- 存储缓存的应用程序项目。

  • 模块- 模块是其他可选的 Python 模块。

  • 私有- 包含的文件由控制器访问,但不能直接由开发人员访问。

  • 上传- 文件由模型访问,但不是由开发人员直接访问。

应用程序编程接口

在 web2py 中,模型控制器视图在为开发人员导入某些对象的环境中执行。

全局对象- 请求、响应、会话、缓存。

Helpers - web2py 包含 helper 类,可用于以编程方式构建 HTML。它对应于 HTML 标签,称为“HTML 助手”

例如,A、B、FIELDSET、FORM 等。

会议

会话可以定义为服务器端信息存储,该信息在整个 Web 应用程序的用户交互过程中持续存在。

web2py中的Session是存储类的实例。

例如,变量可以存储在会话中:

session.myvariable = "hello"

该值可以检索为

a = session.myvariable

只要同一用户在同一会话中执行代码,就可以检索变量的值。

web2py 中用于会话的重要方法之一是“忘记” -

session.forget(response);

它指示 web2py 不要保存会话。

在后台运行任务

HTTP 请求到达 Web 服务器,Web 服务器在自己的线程中并行处理每个请求。活动的任务在前台进行,而其他任务则在后台进行。管理后台任务也是 web2py 的主要功能之一。

耗时的任务最好保留在后台。下面列出了一些管理后台任务的机制 -

  • 克朗

  • 队列

  • 调度程序

克朗

在 web2py 中,CRON提供了在指定的时间间隔内运行任务的能力。每个应用程序都包含一个 CRON 文件,它定义了其功能。

调度程序

内置调度程序通过设置优先级帮助在后台运行任务。它提供了创建、调度和修改任务的机制。

计划的事件在文件名“scheduler.py”的模型中列出。

构建应用程序

我们概述了在 web2py 中创建模型和控制器。在这里,我们将重点关注名为“Contacts”的应用程序的创建。该应用程序需要维护一个公司列表以及在这些公司工作的人员列表。

模型的创建

这里,数据字典的表的标识就是模型。联系人应用程序的模型将在“ models ”文件夹下创建。该文件存储在models/db_contacts.py中。

# in file: models/db_custom.py
db.define_table('company', Field('name', notnull = True, unique = True), format = '%(name)s')
db.define_table(
   'contact',
   Field('name', notnull = True),
   Field('company', 'reference company'),
   Field('picture', 'upload'),
   Field('email', requires = IS_EMAIL()),
   Field('phone_number', requires = IS_MATCH('[\d\-\(\) ]+')),
   Field('address'),
   format = '%(name)s'
)

db.define_table(
   'log',
   Field('body', 'text', notnull = True),
   Field('posted_on', 'datetime'),
   Field('contact', 'reference contact')
)

创建上述文件后,可以通过 URL http://127.0.0.1:8000/contacts/appadmin访问这些表

创建控制器

控制器将包括一些用于列出、编辑和删除联系人的功能。

# in file: controllers/default.py
def index():return locals()
def companies():companies = db(db.company).select(orderby = db.company.name)
return locals()

def contacts():company = db.company(request.args(0)) or redirect(URL('companies'))
contacts = db(db.contact.company == company.id).select(orderby = db.contact.name)
return locals()

@auth.requires_login()
def company_create():form = crud.create(db.company, next = 'companies')
return locals()

@auth.requires_login()
def company_edit():company = db.company(request.args(0)) or redirect(URL('companies'))
form = crud.update(db.company, company, next='companies')
return locals()

@auth.requires_login()
def contact_create():db.contact.company.default = request.args(0)
form = crud.create(db.contact, next = 'companies')
return locals()

@auth.requires_login()
def contact_edit():contact = db.contact(request.args(0)) or redirect(URL('companies'))
form = crud.update(db.contact, contact, next = 'companies')
return locals()

def user():return dict(form = auth())

视图的创建及其输出将在下一章中讨论。

Web2py - 视图

web2py 框架在其应用程序中使用模型控制器视图。它在视图中包含稍微修改的 Python 语法,以获得更易读的代码,而不会对正确的 Python 使用施加任何限制。

web2py视图的主要目的是将 python 代码嵌入到 HTML 文档中。然而,它面临一些问题,如下 -

  • 对 HTML 文档中嵌入的 python 代码进行转义。
  • 基于Python的缩进,这可能会影响HTML规则。

为了避免这些问题,web2py 在视图部分使用分隔符 {{..}}。分隔符有助于转义嵌入的 python 代码。它还有助于遵循 HTML 缩进规则。

{{..}}分隔符中包含的代码包含非预期的 Python 代码。由于Python通常使用缩进来分隔代码块,因此应该以正确的方式维护分隔符内的非预期代码。为了克服这个问题,web2py 使用“pass”关键字。

以一行开头的代码块以冒号结尾,并以以 pass 开头的行结束。

注意- pass 是一个 Python 关键字,它不是 web2py 关键字。

以下代码显示了 pass 关键字的实现 -

{{
   if num > 0:
      response.write('positive number')
   else:
      response.write('negative number')
      pass
}}

HTML 助手

web2py 包含可用于以编程方式构建 HTML 的帮助程序类。它对应于 HTML 标签,称为“HTML 助手”。

例如 -

[(A('Home', _href = URL('default', 'home')), False, None, []), ...]

这里,A是对应于HTML的锚点<a>标签的帮助器。它以编程方式构建 HTML 锚点<a>标记。

HTML 助手由两种类型组成,即位置参数命名参数。

  • 位置参数被解释为包含在 HTML 打开和关闭标记之间的对象。

  • 以下划线开头的命名参数被解释为 HTML 标签。

帮助程序在字符串序列化中也很有用,可以使用_str_和 xml 方法。例如 -

>>> print str(DIV(“hello world”))

输出

<div> hello world </div>

注意- HTML 帮助程序提供文档对象模型 (DOM) 的服务器端表示。

XML 助手

XML 被称为对象,它封装了不应转义的文本。该文本可能包含也可能不包含有效的 XML。

例如,对于下面提到的代码,它可以包含 JavaScript。

>>> print XML('<script>alert("unsafe!")</script>')

输出

<script> alert(“unsafe!”)</script>

内置助手

web2py 中使用了许多内置帮助器。下面列出了一些 HTML 内置帮助程序。

姓名 用法 例子
A 该助手用于构建链接。对应锚标签
[
(A('Home', _href = URL('default', 'home')), False, None, []),
...]
该助手有助于将文本内容设为粗体。
B('<hello>', XML('<i>world</i>'), _class = 'test', _id = 0)
身体 这个助手制作页面的主体。它还包括一个乘法运算符来增加中断次数。
BR()
代码 它对 Python、C、C++ 和 web2py 代码执行语法突出显示。该助手还能够链接 API 文档。
CODE('print "hello"', language = 'python').xml()
现场设置 它创建一个输入字段及其标签。
FIELDSET('Height:', INPUT(_name = 'height'), _class = 'test')
它有助于标记 HTML 页面的 <head> 标记。
HEAD(TITLE('<hello>'))
免疫组化 它有助于为给定的 HTML 页面嵌入图像。
IMG(_src = 'http://example.com/image.png',_alt = 'test')

自定义助手

这些助手用于根据要求自定义标签。web2py 使用以下自定义助手 -

标签

web2py 使用 TAG 作为通用标签生成器。它有助于生成定制的 XML 标签。一般语法如下 -

{{ = TAG.name('a', 'b', _c = 'd')}}

它生成的 XML 代码为:<name c = "d">ab</name>

TAG 是一个对象,TAG.name或者TAG['name']是一个返回临时辅助类的函数。

菜单

该助手创建列表项或菜单项值的列表,生成表示菜单的树状结构。菜单项列表的形式为response.menu。例如 -

print MENU([['One', False, 'link1'], ['Two', False, 'link2']])

输出将显示如下 -

<ul class = "web2py-menu web2py-menu-vertical">
   <li><a href = "link1">One</a></li>
   <li><a href = "link2">Two</a></li>
</ul>

美化

它有助于构建复合对象的表示,包括列表和字典。例如,

{{ = BEAUTIFY({"a": ["hello", XML("world")], "b": (1, 2)})}}

它返回一个可序列化为 XML 的 XML 对象,并带有其构造函数参数的表示形式。在这种情况下,表示为 -

{"a": ["hello", XML("world")], "b": (1, 2)}

输出将呈现为 -

<table>
   <tr>
      <td>a</td>
      <td>:</td>
      <td>hello<br />world</td>
   </tr>
   
   <tr>
      <td>b</td>
      <td>:</td>
      <td>1<br />2</td>
   </tr>
</table>

服务器端 DOM 渲染

服务器端渲染允许用户预渲染 web2py 组件的初始状态。所有派生的助手都提供搜索元素和在服务器端渲染 DOM 的元素。

元素返回与指定条件匹配的第一个子元素。另一方面,元素返回所有匹配子元素的列表。两者都使用相同的语法。

这可以通过以下示例来证明 -

a = DIV(DIV(DIV('a', _id = 'target',_class = 'abc')))
d = a.elements('div#target')
d[0][0] = 'changed'
print a

输出如下:

<div><div><div id = "target" class = "abc">changed</div></div></div>

页面布局

视图用于向最终用户显示输出。它可以扩展并包含其他视图。这将实现一个树状结构。

示例 - “index.html”扩展为“layout.html”,其中可以包含“menu.html”,而“menu.html”又包含“header.html”

{{extend 'layout.html'}}
<h1>Hello World</h1>
{{include 'page.html'}}

例子

在前面的章节中,我们为公司模块创建了模型和控制器。现在,我们将重点关注视图的创建,这有助于渲染数据的显示。

默认情况下,web2py中的视图包括layout.htmlindex.html,它们定义了显示数据的整体部分。

{{extend 'layout.html'}}
<h2>Companies</h2>

<table>
   {{for company in companies:}}
   <tr>
      <td>{{ = A(company.name, _href = URL('contacts', args = company.id))}}</td>
      <td>{{ = A('edit', _href = URL('company_edit', args = company.id))}}</td>
   </tr>
   
   {{pass}}
   <tr>
      <td>{{ = A('add company', _href = URL('company_create'))}}</td>
   </tr>
	
</table>

输出如下 -

视图创建

Web2py - 数据库抽象层

数据库抽象层 (DAL)被认为是 web2py 的主要优势。DAL 向底层 SQL 语法公开了一个简单的应用程序编程接口 (API)。

在本章中,我们将了解 DAL 的重要应用,例如构建查询以有效地按标签搜索以及构建分层类别树。

DAL 的一些重要特征是 -

  • web2py 包含一个数据库抽象层 (DAL),这是一个将 Python 对象映射到数据库对象的 API。数据库对象可以是查询、表和记录。

  • DAL使用数据库后端指定的方言动态实时生成SQL,因此开发人员不需要编写完整的SQL查询。

  • 使用 DAL 的主要优点是应用程序可以与不同类型的数据库移植。

DAL 入门

web2py 中的大多数应用程序都需要数据库连接。因此,构建数据库模型是应用程序设计的第一步。

考虑新创建的名为“helloWorld”的应用程序。数据库是在应用程序的模型下实现的。各个应用程序的所有模型都包含在名为 - models/db_custom.py 的文件中。

以下步骤用于实现 DAL -

第 1 步 - DAL 构造函数

建立数据库连接。这是使用 DAL 对象创建的,也称为 DAL 构造函数。

db = DAL ('sqlite://storage.sqlite')

DAL 的显着特点是它允许与同一数据库或不同数据库甚至不同类型的数据库进行多个连接。可以看出,该行已经在文件models/db.py中。因此,您可能不需要它,除非您删除了它或需要连接到不同的数据库。默认情况下,web2py 连接到存储在文件storage.sqlite中的 SQLite 数据库。

该文件位于应用程序的数据库文件夹中。如果该文件不存在,则该文件由 web2py 在应用程序首次执行时创建。

SQLite 速度很快,并将所有数据存储在一个文件中。这意味着您的数据可以轻松地从一个应用程序传输到另一个应用程序。事实上,SQLite 数据库是由 web2py 与应用程序打包在一起的。它提供完整的 SQL 支持,包括转换、连接和聚合。

SQLite 有两个缺点。

  • 一是它不强制列类型,并且除了添加和删除列之外没有 ALTER TABLE。

  • 另一个缺点是整个数据库被任何需要写访问的事务锁定。

第 2 步 - 表构造器

一旦与数据库建立连接,我们就可以使用define_table方法来定义新表。

例如 -

db.define_table('invoice',Field('name'))

Table构造函数中也使用了上述方法。表构造函数的语法是相同的。第一个参数是表名称,后面是Field(s)列表。字段构造函数采用以下参数 -

先生编号 参数和用法
1

字段名称

表中的字段名称。

2

字段类型

接受任何数据类型的值,例如字符串(默认)、文本、布尔值、整数等。

3

长度

定义最大长度。

4

默认=无

这是插入新记录时的默认值。

5

更新=无

这与默认值相同,但该值仅在更新时使用,而不在插入时使用。

6

不为空

这指定字段值是否可以为 NULL。

7

可读=真

这指定该字段在表单中是否可读。

8

可写=真

这指定该字段在表单中是否可写。

9

标签=“字段名称”

这是表单中该字段使用的标签。

Define_table方法还采用三个命名参数 -

句法

db.define_table('....',migrate=True, fake_migrate=False, format = '%(id)s')
  • migrate = True - 这指示 web2py 创建表(如果不存在),或者更改它(如果与模型定义不匹配)。

  • fake_migrate = False - 如果模型与数据库表内容匹配,则设置 fake_migrate = True 这有助于 web2py 重建数据。

  • format = '%(id)s' - 这是一个格式字符串,用于确定给定表上的记录应如何表示。

生成原始 SQL

使用 DAL,我们可以建立与数据库的连接,并使用表构造函数和字段构造函数创建新表及其字段。

有时,需要生成SQL语句以符合必要的输出。web2py 包含各种函数,有助于生成原始 SQL,如下所示 -

_插入

它有助于获取给定表的插入语句。例如,

print db.person._insert(name ='ABC')

它将检索名为“person”的表的插入语句。

SQL 语句输出 -

INSERT INTO person(name) VALUES ('ABC');

_数数

它有助于获取 SQL 语句,从而给出记录数。例如,考虑一个名为“person”的表,我们需要查找名为“ABC”的人数。

print db(db.person.name ==' ABC ')._count()

SQL 语句输出 -

SELECT count(*) FROM person WHERE person.name = ' ABC ';

_选择

它有助于获取选择的 SQL 语句。例如,考虑一个名为“person”的表,我们需要查找名为“ABC”的人员列表。

print db(db.person.name == ' ABC ')._select()

SQL 语句输出 -

SELECT person.name FROM person WHERE person.name = ' ABC ';

_删除

它有助于获取删除 SQL语句。例如,考虑名为“person”的表,我们需要删除名为“ABC”的语句

print db(db.person.name == ' ABC ')._delete()

SQL 语句输出 -

DELETE FROM person WHERE person.name = ' ABC ';4

_更新

它有助于获取更新的 SQL 语句。例如,考虑名为“person”的表,我们需要用其他值更新列名

print db(db.person.name == ' ABC ')._update()

SQL 语句输出 -

UPDATE person SET WHERE person.name = ’Alex’;

DAL 问题(陷阱)

SQLite

SQLite 缺乏对删除或更改列的支持。从表中删除字段会使其在数据库中保持活动状态,因此 web2py 将不会意识到所做的任何更改。

在这种情况下,有必要设置 fake_migrate = True,这将有助于重新定义元数据,以便任何更改(例如更改或删除)都将保留在 web2py 的知识之下。

SQLite 不支持布尔类型。为此,web2py 在内部将布尔值映射到 1 个字符串,其中“T”和“F”分别代表trueFalse

MySQL

MySQL 不支持 ALTER TABLE 功能。因此,数据库的迁移涉及多次提交。可以通过在定义数据库时设置参数fake_migrate = True来避免这种情况,这将持久化所有元数据。

甲骨文

Oracle不支持记录分页功能。它还缺乏对关键字 OFFSET 或 limit 的支持。为此,web2py 借助 DAL 的复杂三向嵌套选择来实现分页。如果使用了 Oracle 数据库,DAL 需要自行处理分页。

Web2py - 表单和验证器

web2py 具有强大的表单生成功能。在 web2py 中构建表单的四种不同方法如下 -

  • FORM - 就 HTML 帮助程序而言,它被视为低级实现。FORM 对象知道它的字段内容。

  • SQLFORM - 它提供对现有数据库的创建、更新和删除功能。

  • SQLFORM.factory - 它被认为是 SQLFORM 顶部的抽象层,它生成类似于 SQLFORM 的表单。在这里,不需要创建新的数据库。

  • CRUD 方法- 顾名思义,它提供创建、检索、更新和删除功能以及基于 SQLFORM 的类似功能。

形式

考虑一个应用程序,它接受用户的输入并有一个“提交”按钮来提交响应。

控制器

“default.py”控制器将包含以下关联函数

def display_form():
   return dict()

看法

关联视图“default/display_form.html”会将 HTML 中的表单显示呈现为:

{{extend 'layout.html'}}
<h2>Basic Form</h2>

<form enctype = "multipart/form-data" action = "{{= URL()}}" method = "post">
   Your name:
   <input name = "name" />
   <input type = "submit" />
</form>

<h2>Submitted variables</h2>
{{= BEAUTIFY(request.vars)}}

上面的例子是普通的 HTML 表单,它要求用户输入。可以使用 FORM 对象等帮助器生成相同的表单。

控制器

def display_form():
   form = FORM('Value:', INPUT(_value = 'name'), INPUT(_type = 'submit'))
   return dict(form = form)

“default.py”控制器中的上述函数包含 FORM 对象(HTML 帮助器),它有助于创建表单。

看法

{{extend 'layout.html'}}
<h2>Basic form</h2>

{{= form}}
<h2>Submitted variables</h2>

{{= BEAUTIFY(request.vars)}}

由语句{{= form}}生成的form 序列化 FORM 对象。当用户填写表单并单击提交按钮时,表单会自行提交,变量request.vars.value及其输入值将显示在底部。

SQL格式

它有助于为现有数据库创建表单。下面讨论其实施步骤。

使用DAL与数据库建立连接,这是使用DAL对象创建的,也称为DAL构造函数。建立连接后,用户可以创建相应的表。

db = DAL('sqlite://storage.sqlite')
db.define_table('employee', Field('name', requires = IS_NOT_EMPTY()))

因此,我们创建了一个名为“employee”的表。控制器使用以下语句构建表单和按钮 -

form = SQLFORM(
   db.mytable,
   record = mytable_index,
   deletable = True,
   submit_button = T('Update')
)

因此,对于创建的员工表,控制器中的修改将是 -

def display_form():
   form = SQLFORM(db.person)

View中没有任何修改。在新控制器中,有必要构建一个 FORM,因为在模型中定义了从表 db.employee 构建的 SQLFORM 构造函数。新的形式,当序列化时,显示如下 -

<form enctype = "multipart/form-data" action = "" method = "post">
   
   <table>
      <tr id = "employee_name__row">
         <td>
            <label id = "person_name__label" for = "person_name">Your name: </label>
         </td>
         
         <td>
            <input type = "text" class = "string" name = "name" value = "" id = "employee_name" />
         </td>
         
         <td></td>
      </tr>

      <tr id = "submit_record__row">
         <td></td>
         <td><input value = "Submit" type = "submit" /></td>
         <td></td>
      </tr>
		
   </table>

   <input value = "9038845529" type = "hidden" name = "_formkey" />
   <input value = "employee" type = "hidden" name = "_formname" />
	
</form>

表单中的所有标记的名称均源自表和字段名称。

SQLFORM对象还通过将上传的文件保存在“uploads”文件夹中来处理“上传”字段。这是自动完成的。SQLFORM 在“textareas”的帮助下以复选框和文本值的形式显示“布尔”值。

SQLFORM 还使用 process 方法。如果用户想要将值与关联的 SQLFORM 一起保存,则这是必需的。

如果form.process(keepvalues = True)则它被接受。

例子

def display_form():
   form = SQLFORM(db.employee)
if form.process().accepted:
   response.flash = 'form accepted'

elif form.errors:
   response.flash = 'form has errors'
else:
   response.flash = 'please fill out the form'

return dict(form = form)

SQLFORM.factory

有时,用户需要以已有数据库表的方式生成表单,而无需数据库的实现。用户只是想利用 SQLFORM 功能。

这是通过form.factory完成的,并在会话中维护。

def form_from_factory():
   form = SQLFORM.factory(
      Field('your_name', requires = IS_NOT_EMPTY()),
      Field('your_image', 'upload'))

   if form.process().accepted:
      response.flash = 'form accepted'
      session.your_name = form.vars.your_name
      session.your_image = form.vars.your_image
   elif form.errors:
      response.flash = 'form has errors'

   return dict(form = form)

该表单将显示为 SQLFORM,其字段为名称和图像,但数据库中没有这样的现有表。

“default/form_from_factory.html”视图将表示为 -

{{extend 'layout.html'}}
{{= form}}

增删改查方法

CRUD是在 SQLFORM 之上使用的 API。顾名思义,它用于创建、检索、更新和删除适当的表单。

CRUD 与 web2py 中的其他 API 相比,没有公开;因此,有必要进口。

from gluon.tools import Crud
crud = Crud(db)

上面定义的 CRUD 对象提供以下 API -

先生编号 API 和功能
1

crud.tables()

返回数据库中定义的表的列表。

2

crud.create(db.表名)

返回表 tablename的创建表单。

3

crud.read(db.表名, id)

返回表名和记录 ID的只读形式。

4

crud.delete(db.表名, id)

删除记录

5

crud.select(db.表名,查询)

返回从表中选择的记录列表。

6

crud.search(db.表名)

返回一个元组(表单,记录),其中表单是搜索表单。

7

增删改查()

根据 request.args() 返回上述内容之一。

创建表格

让我们创建一个表格。请遵循下面给出的代码。

模型

将在应用程序的models文件夹下创建一个新模型。文件的名称为“dynamic_search.py​​”

def build_query(field, op, value):
   if op == 'equals':
      return field == value
   
   elif op == 'not equal':
      return field != value
   
   elif op == 'greater than':
      return field > value
   
   elif op == 'less than':
      return field < value
   
   elif op == 'starts with':
      return field.startswith(value)
   
   elif op == 'ends with':
      return field.endswith(value)
   
   elif op == 'contains':
      return field.contains(value)

def dynamic_search(table):
   tbl = TABLE()
   selected = []
   ops = ['equals', 
      'not equal',
      'greater than',
      'less than',
      'starts with',
      'ends with',
      'contains']
		
query = table.id > 0

for field in table.fields:
   chkval = request.vars.get('chk'+field,None)
   txtval = request.vars.get('txt'+field,None)
   opval = request.vars.get('op'+field,None)
	
row = TR(TD(INPUT(_type = "checkbox",_name = "chk"+field,value = chkval == 'on')),
   TD(field),TD(SELECT(ops,_name = "op"+field,value = opval)),
   TD(INPUT(_type = "text",_name = "txt"+field,_value = txtval)))
	
tbl.append(row)

if chkval:
   if txtval:
      query &= build_query(table[field], opval,txtval)
      selected.append(table[field])
      form = FORM(tbl,INPUT(_type="submit"))
      results = db(query).select(*selected)
   return form, results

控制器

控制器部分下的关联文件“dynamic_search.py​​”将包含以下代码 -

def index():
   form,results = dynamic_search(db.things)
   return dict(form = form,results = results)

看法

我们可以用下面的视图来渲染它。

{{extend 'layout.html'}}
{{= form}}
{{= results}}

这是它的样子 -

看法

Web2py - 电子邮件和短信

web2py 包括向用户发送电子邮件和短信的功能。它使用库来发送电子邮件和短信。

设置电子邮件

内置类gluon.tools.Mail类用于在 web2py 框架中发送电子邮件。邮件程序可以用此类来定义。

from gluon.tools import Mail
mail = Mail()
mail.settings.server = 'smtp.example.com:25'
mail.settings.sender = 'abc@example.com'
mail.settings.login = 'username:password'

每次发送电子邮件时,都会对上例中提到的发件人电子邮件以及密码进行身份验证。

如果用户需要实验或用于某些调试目的,可以使用以下代码来实现。

mail.settings.server = 'logging'

现在,所有电子邮件都不会发送,但会记录在控制台中。

发送电子邮件

一旦我们使用邮件对象设置了电子邮件的配置设置,就可以将电子邮件发送给许多用户。

mail.send()的完整语法如下 -

send(
   to, subject = 'Abc',
   message = 'None', attachments = [],
   cc = [], bcc = [], reply_to = [],
   sender = None, encoding = 'utf-8',
   raw = True, headers = {}
)

下面给出了mail.send()的实现。

mail.send(
   to = ['sender@example.com'], subject = 'hello',
   reply_to = 'abc@example.com',
   message = 'Hello ! How are you?'
)

Mail根据邮件服务器的响应返回一个布尔表达式,表明邮件已被最终用户接收。如果成功向用户发送电子邮件,则返回True 。

to、 ccbcc属性包括要发送邮件的有效电子邮件地址列表。

发送短信

发送 SMS 消息的实现与在 web2py 框架中发送电子邮件不同,因为它需要第三方服务来将消息转发给接收者。第三方服务不是免费服务,并且根据地理区域(不同国家)会有明显差异。

web2py 使用一个模块来帮助通过以下过程发送短信 -

from gluon.contrib.sms_utils
import SMSCODES, sms_email
email = sms_email('1 (111) 111-1111','T-Mobile USA (abc)')
mail.send(to = email, subject = 'test', message = 'test')

在上面的示例中,SMSCODES是由 web2py 维护的字典,它将主要电话公司的名称映射到电子邮件地址后缀。

电话公司通常将来自第三方服务的电子邮件视为垃圾邮件。更好的方法是电话公司自己转发短信。每个电话公司的存储中的每个手机号码都有一个唯一的电子邮件地址,并且短信可以直接发送到该电子邮件地址。

在上面的例子中,

  • sms_email函数接受电话号码(作为字符串),返回电话的电子邮件地址。

  • 脚手架应用程序包含多个文件。其中之一是 models/db.py,它导入了四个。

  • gluon.tools中的类还包括邮件库并定义了各种全局对象。

  • 脚手架应用程序还定义了 auth 对象所需的表,例如db.auth_user。默认的脚手架应用程序旨在最大限度地减少文件数量,而不是模块化。特别是,模型文件db.py包含配置,在生产环境中,最好将其保存在单独的文件中。

在这里,我们建议创建一个配置文件 -

from gluon.storage import Storage
   settings = Storage()
   settings.production = False
   
   if