视图

未匹配的标注

Masonite 中的视图是在控制器中返回 HTML 的好方法。视图具有层次结构、许多帮助程序和逻辑控件,这是将业务逻辑与界面逻辑分开的好方法。

入门

默认情况下,视图的所有模板都位于 templates 目录中。要创建模板,只需在此目录中创建一个 .html 文件,我们稍后将引用该文件。

<!-- Template in templates/welcome.html -->
<html>
    <body>
        <h1>Hello, {{ name }}</h1>
    </body>
</html>

在你的控制器文件中,你可以引用此模板:

from masonite.views import View

class WelcomeController(Controller):

  def show(self, view: View):
    view.render('welcome', {
        "name": "Joe"
    })

这里的第一个参数是模板的名称,第二个参数应该是你在模板中引用的变量字典。

如果你在另一个目录中有模板,则可以使用「点表示法」来引用这些模板名称

from masonite.views import View

class WelcomeController(Controller):

  # Template is templates/greetings/welcome.html
  def show(self, view: View):
    view.render('greeting.welcome', {
        "name": "Joe"
    })

共享视图

共享视图是当你希望变量在所有呈现的模板中可用时。这可能是经过身份验证的用户、版权年份或你希望在模板之间共享的任何其他内容。

视图共享需要你添加字典:

from masonite.facades import View

View.share({
  'copyright': '2021'
})

然后在你的模板中,你可以执行以下操作:

<div>
  Copyright {{ copyright }}
</div>

你通常会在应用程序的服务提供者中执行此操作(如果没有,你应该创建一个)):

from masonite.facades import View

class AppProvider(Provider):

    def register(self):
        View.share({'copyright': '2021'})

合成视图

类似于视图共享,视图合成允许你在特定模板之间共享模板

View.composer('dashboard', {'copyright': '2021'})

你还可以传递模板列表:

View.composer(['dashboard', 'dashboard/users'], {'copyright': '2021'})

你通常会在应用程序的服务提供者中执行此操作(如果没有,你应该创建一个)):

from masonite.facades import View

class AppProvider(Provider):

    def register(self):
        View.composer('dashboard', {'copyright': '2021'})

助手函数

在视图中有相当多的内置助手函数。以下是所有视图助手函数的详尽列表:

Request

你可以获取请求类:

<p> Path: {{ request().path }} </p>

Asset

你可以获取静态资源的位置:

你可以使用 asset 助手函数得到静态资源的路径:

...
<img src="{{ asset('s3', 'profile.jpg') }}" alt="profile">
...

这将渲染出如下 URL:

<img src="https://s3.us-east-2.amazonaws.com/bucket/profile.jpg" alt="profile">

有关如何设置路径的信息,请参阅你的 filesystems.py 配置。

CSRF 表单

你可以创建一个用于表单的 CSRF 令牌隐藏字段:

<form action="/some/url" method="POST">
    {{ csrf_field }}
    <input ..>
</form>

CSRF 令牌

你只能获得生成的令牌。这对于需要将 CSRF 令牌传递到后端以进行 AJAX 调用的 JS 前端很有用

<p> Token: {{ csrf_token }} </p>

获取当前用户

你还可以获取当前经过身份验证的用户。这与执行 request.user() 相同。

<p> User: {{ auth().email }} </p>

现在,这将把这个表单作为 PUT 请求提交。

路由

你可以使用以下方法通过其名称获取路由:

<form action="{{ route('route.name') }}" method="POST">
    ..
</form>

如果你的路由包含需要传递的变量,你可以提供一个字典作为第二个参数。

<form action="{{ route('route.name', {'id': 1}) }}" method="POST">
    ..
</form>

或传递一个数组列表:

<form action="{{ route('route.name', [1]) }}" method="POST">
    ..
</form>

重定向返回

这对于重定向回上一页很有用。如果你使用了这个助手函数,则 request.back() 方法将转到指定位置。在表单提交错误后使用它返回页面通常能得到不错的效果:

<form action="/some/url" method="POST">
    {{ back(request().path) }}
</form>

现在,当你提交表单并且想在控制器中将用户发送的数据传递回来时,你只需执行以下操作:

def show(self, response: Response):
    # Some failed validation
    return response.back()

会话

你可以这样访问会话:

<p> Error: {{ session().get('error') }} </p>

提示:在 会话 文档中了解有关会话的更多信息。

配置

配置函数助手可以让你轻松地在模板中获取配置值:

<h2> App Name: {{ config('application.name') }}</h2>

Cookie

获取 cookie:

<h2> Token: {{ cookie('token') }}</h2>

Url

获取某个位置的 URL:

<form action="{{ url('/about', full=True) }}" method="POST">

</form>

DD

为了帮助调试,你可以使用 dd() 助手函数

{{ dd(variable) }}

视图过滤器

Jinja2 允许在你的视图中添加过滤器。在我们解释如何向所有模板添加过滤器之前,让我们准确解释一下什么是视图过滤器。

过滤器可以附加到视图变量以更改和修改它们。例如,你可能有一个想要变成 slug 的变量,并且具有以下内容:

{{ variable|slug }}

在 Masonite 中,这个 slug 过滤器只是一个将变量作为参数的函数,看起来像一个简单的函数,如下所示:

def slug(variable):
    return variable.replace(' ', '-')

仅此而已!重要的是要注意,它过滤的变量总是作为第一个参数传递,所有其他参数都在之后传递,所以我们可以这样做:

{{ variable|slug('-') }}

然后我们的函数看起来像:

def slug(variable, replace_with):
    return variable.replace(' ', replace_with)

添加过滤器

添加过滤器通常在应用程序的服务提供者内完成(如果你没有,你应该创建一个):

from masonite.facades import View

class AppProvider(Provider):

    def register(self):
        View.('slug', self.slug)

    @staticmethod
    def slug(item):
        return item.replace(' ', '-')

视图测试

视图测试只是可以在模板中使用的自定义布尔表达式。我们可能希望对特定对象运行布尔测试以断言它们通过了测试。例如,我们可能想测试用户是否是这样一家公司的所有者:

<div>
    {% if user is a_company_owner %}
        hey boss
    {% else %}
        you are an employee
    {% endif %}
</div>

为了做到这一点,我们需要在 View 类上添加一个测试。我们可以再次在应用程序 服务提供者 中执行此操作。

代码很简单,看起来像这样:

from masonite.facades import View

def a_company_owner(user):
    # Returns True or False
    return user.owner == 1

class AppProvider(Provider):

    def register(self):
        # template alias
        View.test('a_company_owner', a_company_owner)

就这样,现在我们可以在模板中使用 a_company_owner,就像上面的第一个代码片段一样!

请注意,我们只提供了函数,并没有实例化任何东西。我们提供的函数或对象需要有 1 个参数,即我们正在测试的对象或字符串。

添加环境

视图中的环境是模板的目录。如果你正在开发包或构建基于模块化的应用程序,你可能需要为模板注册不同的目录。这将允许 Masonite 在引用它们进行渲染时定位你的视图。 这样做的好地方是在服务提供者的 register 方法中。

有两种不同的方式注册环境目录。

第一个加载器是一个「包」加载器。这在注册包时使用。为此,你只需将其注册到包模块路径即可。这适用于大多数包目录。

from masonite.facades import View

View.add('module_name/directory')

另一个加载器是 FileSystem 加载器。这应该在目录路径不是模块而只是文件系统路径时使用:

from jinja2.loaders import FileSystemLoader
from masonite.facades import View

View.add(
    os.path.join(
        os.getcwd(), 'package_views'
    )
, loader=FileSystemLoader)

视图语法

Jinja2

以下是 Masonite 用于构建视图的 Jinja2 语法的一些示例。

行语句

需要注意的是,Jinja2 语句可以用多行代码重写,line 语句在 Masonite 中是首选。与 Jinja2 多行代码相呼应,因此命名行语句。

所以 Jinja2 的语法看起来像这样:

{% if expression %}
    <p>do something</p>
{% endif %}

可以用 line 语句语法这样重写:

@if expression
    <p>do something</p>
@endif

重要的是要注意这些是多行语句。这意味着在执行这些操作时不会有其他任何事情发生。例如,你不能这样做:

<form action="@if expression: 'something' @endif">

</form>

但是你可以使用常规格式来实现:

<form action="{% if expression %} 'something' {% endif %}">

</form>

无论你选择哪种语法都取决于你。

请注意,如果你使用不应使用 Masonite 呈现的 @ 符号,则会引发错误。一个例子是当你在 CSS 中使用 @media 标签。在这种情况下,你需要将此语句包装在 {%raw%}{% endraw%} 块中。

变量

你可以使用 {{ }} 字符显示变量或字符串文本:

<p>
    {{ variable }}
</p>
<p>
    {{ 'hello world' }}
</p>

IF 语句

if 语句与 python 类似,但需要一个 endif!

行语句示例:

@if expression
    <p>do something</p>
@elif expression
    <p>do something else</p>
@else
    <p>above all are false</p>
@endif

使用 Jinja2 语法替代:

{% if expression %}
    <p>do something</p>
{% elif %}
    <p>do something else</p>
{% else %}
    <p>above all are false</p>
{% endif %}

For 循环

For 循环看起来类似于常规的 python 语法。

行语句示例:

@for item in items
    <p>{{ item }}</p>
@endfor

使用 Jinja2 语法替代:

{% for item in items %}
    <p>{{ item }}</p>
{% endfor %}

Include 语句

include 语句对于包含其他模板很有用。

行语句示例:

@include 'components/errors.html'

<form action="/">

</form>

使用 Jinja2 语法替代:

{% include 'components/errors.html' %}

<form action="/">

</form>

任何有重复代码的地方都可以拆分出来并放入包含模板中。这些模板将可以访问当前模板中的所有变量。

Extends

这对于让子模板扩展父模板很有用。每个模板只能有 1 个扩展:、

行语句示例:

@extends 'components/base.html'

@block content
    <p> read below to find out what a block is </p>
@endblock

使用 Jinja2 语法替代:

{% extends 'components/base.html' %}

{% block content %}
    <p> read below to find out what a block is </p>
{% endblock %}

Blocks 代码块

块是可用作父模板的占位符的代码段。这些仅在与上面的 Extend一起使用时才有用。 base.html 模板是父模板并包含在子模板 blocks.html 中定义的块。

行语句示例:

<!-- components/base.html -->
<html>
    <head>
        @block css
        <!-- block named "css" defined in child template will be inserted here -->
        @endblock
    </head>

<body>
    <div class="container">
        @block content
        <!-- block named "content" defined in child template will be inserted here -->
        @endblock
    </div>

@block js
<!-- block named "js" defined in child template will be inserted here -->
@endblock

</body>
</html>
<!-- components/blocks.html -->
@extends 'components/base.html'

@block css
    <link rel=".." ..>
@endblock

@block content
    <p> This is content </p>
@endblock

@block js
    <script src=".." />
@endblock

使用 Jinja2 语法替代:

<!-- components/base.html -->
<html>
    <head>
        {% block css %}
        <!-- block named "css" defined in child template will be inserted here -->
        {% endblock %}
    </head>

<body>
    <div class="container">
        {% block content %}
        <!-- block named "content" defined in child template will be inserted here -->
        {% endblock %}
    </div>

{% block js %}
<!-- block named "js" defined in child template will be inserted here -->
{% endblock %}

</body>
</html>
<!-- components/blocks.html -->
{% extends 'components/base.html' %}

{% block css %}
    <link rel=".." ..>
{% endblock %}

{% block content %}
    <p> This is content </p>
{% endblock %}

{% block js %}
    <script src=".." />
{% endblock %}

如你所见,代码块是基本的元素,可以使用 Jinja2 和 line 语句定义。它允许你构建模板并减少重复代码。

子模板中定义的块将被传递给父模板。

你通常会在你的应用程序中执行此操作
服务提供者

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/masonite/4.0/fe...

译文地址:https://learnku.com/docs/masonite/4.0/fe...

上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 查看所有版本


暂无话题~