视图
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 语句定义。它允许你构建模板并减少重复代码。
子模板中定义的块将被传递给父模板。
你通常会在你的应用程序中执行此操作
服务提供者
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。