用于enaml的web组件工具包

enaml-web的Python项目详细描述


搪瓷网

构建状态codecoov

一个web组件工具包,用于 让我们用python声明性地构建网站。

您可以使用enaml web使用python、enaml和几行simplejavascript构建"交互式"网站(请参阅simple pandasdataframe viewer示例)。视图状态(DOM)作为一个名称视图存储在服务器上,交互通过在 在客户端和服务器之间使用WebSocket(或轮询)。

为了演示,下面的交互都是用enaml web处理的

带enaml的python交互式网站

示例

请参见"示例"文件夹

简介

要使用enaml web,只需将html标记替换为enaml组件 (大写的标记名)。例如:

fromweb.components.apiimport*enamldefIndex(Html):Head:Title:text="Hello world"Body:H1:text="Hello world"

在这个名称视图的一个实例上调用render(),然后生成html 从视野看。这在静态站点生成器的简单示例中显示:

importenamlfromweb.core.appimportWebApplication# Create an enaml Application that supports web componentsapp=WebApplication()# Import Index from index.enamlwithenaml.imports():fromindeximportIndex# Render the Index.enaml to index.htmlview=Index()withopen('index.html','w')asf:f.write(view.render())

您还可以在请求处理程序中使用它来处理您喜爱的web框架。例如龙卷风 网络您可以这样做:

importenamlimporttornado.webimporttornado.ioloopfromweb.core.appimportWebApplication# Import Index from index.enamlwithenaml.imports():fromindeximportIndexclassIndexHandler(tornado.web.RequestHandler):view=Index()defget(self,request):returnself.view.render(request=request)classApplication(tornado.web.Application):def__init__(self):super(Application,self).__init__([(r'/',IndexHandler)],)if__name__=="__main__":web_app=WebApplication()app=Application()app.listen(8888)tornado.ioloop.IOLoop.current().start()

那么与普通的html相比有什么优势呢?

它和HTML一样简单,但它是Python,所以你可以循环列表,有条件地呈现, 格式变量等。

此外,它不仅格式化模板,服务器还维护页面状态,以便 您可以在呈现页面后与之交互。这是没有别的东西 python模板框架可以做到(据我所知)。

工作原理

它生成一个由lxml元素组成的dom。

固有安全性

由于生成了lxml dom,这意味着您的代码本质上是安全的 注入,因为它会自动转义所有属性。而且结束标记不能 不小心错过。

atom框架通过强制运行时类型提供额外的安全性 检查和可选验证。

可通过模板和块扩展

与其他模板引擎一样,enaml web提供了一个"block"节点,允许 您可以定义模板中可以重写或扩展的部分。

enaml还提供模式节点来处理条件语句、循环, 基于列表或模型的动态节点,以及由更复杂的 模板(例如自动生成表单)。

不需要模板标记

许多模板引擎需要使用包装在{%}中的"模板标记" 或者类似于允许使用python代码转换变量。

因为enaml是python,所以可以直接在 你的恩AML组件和模板。您不需要任何模板标记。

测试更容易

因为内部表示是lxml节点,所以可以使用lxml的xpath 查询用于E2E视图测试的DOM。不需要使用无头浏览器和 那些复杂的东西(除非你用了很多js)。

基于组件

由于enaml视图类似于python类,所以可以"子类"并扩展任何 组件并扩展其功能。这使您能够快速构建 可重复使用的部件。

我正在研究几个常用css框架的组件,这样它们就可以 安装并使用。

  1. 物化用户界面
  2. 语义用户界面(即将推出)
  3. 引导(即将推出)
  4. < > >

    数据绑定

    因为enaml web正在生成一个dom,所以可以使用websockets和一些js 操作dom在客户端到服务器之间进行数据绑定。

    可以为每个用户或每个会话共享dom,这样可以轻松地创建 协作页面,或者它们对每个页面都是唯一的。

    数据绑定

    每个节点都是唯一的标识符,可以使用更改事件进行修改。安 示例位于"示例"文件夹中。

    您还可以在服务器上设置客户机触发器事件,并在服务器上设置 在客户端上触发js事件。

    使用:

    1. 在页面中包含enaml.js
    2. 观察html节点的modified事件,并将这些更改传递给 通过WebSocket客户端。
    3. enamljs将事件发送回服务器,相应地更新dom。
    4. < > >

      数据模型

      可以使用enaml的dynamictemplate自动生成和填充表单 节点。使用materalize css实现autoform 框架可以在我的个人回购协议上找到。有了这个,我们可以采用这样的模型:

      fromatom.apiimportAtom,Unicode,Bool,EnumclassMessage(Atom):name=Unicode()email=Unicode()message=Unicode()options=Enum("Email","Phone","Text")sign_up=Bool(True)

      然后使用autoform节点并传入 要呈现窗体的模型。

      fromtemplatesimportBasefromweb.components.apiimport*fromweb.core.apiimportBlockenamldefAddMessageView(Base):page:attrmessageBlock:block=page.contentAutoForm:model<<message

      呈现形式

      带有atom的数据库orm

      有关使用atom处理数据库的信息,请参见atom db

      原始、标记和代码节点

      raw节点将文本解析为dom节点(使用lxml的html解析器)。同样地 标记代码节点分别解析标记和突出显示代码。

      例如,您可以使用wagtal的richtext标记通过:

      fromweb.components.apiimport*fromweb.core.apiimport*fromwagtail.core.templatetags.wagtailcore_tagsimportrichtextfrommyapp.views.baseimportPageenamldefBlogPage(Page):body.cls='template-blogpage'Block:block=parent.contentRaw:source<<richtext(page.body)

      让我们使用web所见即所得编辑器将内容插入到dom中。

      块节点

      您可以定义基本模板,然后使用节点覆盖零件。

      在一个文件中输入:

      fromweb.components.apiimport*fromweb.core.apiimportBlockenamldefBase(Html):attruserattrsiteattrrequestaliascontentHead:Title:text<<site.titleBody:Header:text="Header"Block:content:passFooter:text="Footer"

      然后可以导入该视图并扩展模板并覆盖 块的内容。

      fromtemplatesimportBasefromweb.components.apiimport*fromweb.core.apiimportBlockenamldefPage(Base):page:Block:block=page.contentP:text="Content inserted between Header and Footer"

      块使您可以替换、追加或预处理内容。

      自定义组件

      使用enaml,您可以轻松地创建可重用组件并通过 视图与任何使用常规python导入的python类一样。

      例如,要创建 将breadcrumbs组件具体化 它自动遵循当前的请求路径,只需包含所需的 css/脚本在基本模板中,定义如下所示的组件:

      fromweb.components.apiimport*fromweb.core.apiimportLooperenamldefBreadcrumbs(Nav):nav:attrpath# ex. pass in a tornado request.pathattrcolor=""attrbreadcrumbs<<path[1:-1].split("/")tag='nav'Div:cls='nav-wrapper {}'.format(nav.color)Div:cls='container'Div:cls='col s12'Looper:iterable<<breadcrumbsA:href="/{}/".format("/".join(breadcrumbs[:loop_index+1]))cls="breadcrumb"text=loop_item.title()

      然后按如下方式使用它

      fromweb.components.apiimport*enamldefIndex(Html):Head:Title:text="Hello world"Body:H1:text="Hello world"
      0

      哥特卡斯

      < H5>XT和尾部节点

lxml使用文本和尾部属性设置子节点之前和之后的文本,这可能会造成混淆。

例如,在html中,您可以执行

fromweb.components.apiimport*enamldefIndex(Html):Head:Title:text="Hello world"Body:H1:text="Hello world"
1

要使用enaml进行此操作,您需要执行以下操作:

fromweb.components.apiimport*enamldefIndex(Html):Head:Title:text="Hello world"Body:H1:text="Hello world"
2

注意如何在a而不是p>上设置尾部。 有关详细信息,请参见lxml etree文档

标记属性

在当前实现中,使用的xml标记是类名的小写。 子类化组件时,必须明确地将标记属性设置为 所需的标记名。例如:

fromweb.components.apiimport*enamldefIndex(Html):Head:Title:text="Hello world"Body:H1:text="Hello world"
3

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java是否存在这样一种场景:Java7的Hashmap实现优于Java8的实现   java如何打印这些完整的数组?   java BuildException:未能执行aapt   java如何使用类。未知类型的集合返回的cast()   java准备语句返回错误的值   webview 安卓中的java显示身份验证对话框   java如何重命名列名JPA Hibernate   java查询从特定用户和特定时间段的Oracle表(通过比较原始表和备份表)中选择修改的行   java Youtube视频仅在三星S6设备上加载时自动暂停   未调用java RecyclerView getItemViewType   使用JSch setCommand执行带有源选项的java Shell ping命令时失败   java Hibernate:无法删除|删除分离的实例   Java Spring@MappedSuperclass字段作为子类中的@Id字段   java Android:确定单击了哪个按钮,因为该按钮未在xml中定义   如何计算java阵列内存使用率   使用Java查找按字母顺序排列的第一个字符串   javascript注销功能刷新页面,但页面仍已登录   当接口作为参数提供时,java依赖项注入不起作用   java中带原语的字符串扭曲