创建一个博客

未匹配的标注
本文档最新版为 4.0,旧版本可能放弃维护,推荐阅读最新版!

创建一个博客

前言

文档的这一部分将包含各种教程。这些指南旨在引导您从头到尾使用 Masonite 构建各种类型的项目。我们可能不会详细解释每一节的内容,因为文档的这一部分只是为了让您熟悉 Masonite 的内部工作原理。

因为文档的这一部分是为了让您能够使用 Masonite 编写代码,任何需要进一步说明的地方都在不同的「提示块」中。完成本教程后,或者只是想了解更多关于某个主题的信息,建议您仔细阅读每个提示块,然后按照链接深入阅读参考文档,这将大大提高解释力。

提示块

在整个教程中,您将看到各种提示块。下面是各种颜色所代表的示例。

如果您想了解有关当前正在讨论的主题的更多信息,您将看到绿色的提示块。

你还会看到蓝色的提示块。这些不应该被忽略,通常包含需要进一步理解的背景信息。

安装

本教程假设您已经安装了 Masonite 。如果没有,请务必阅读 安装 指南,以便重新安装并运行 Masonite 。一旦你启动运行了一个,或者如果你已经有正在运行的,请继续。

创建一个博客

在本教程中,我们将介绍如何创建博客。我们将介绍 Masonite 的所有主要系统,它应该会让您有信心尝试更高级的教程或自己构建一个应用程序。

路由

通常, Masonite 开发流程的第一步是创建一个路由。所有路由都位于 routes/web.py 中,非常容易理解。它们由请求方法和路由方法组成。路由只是说明传入的 URI 应该指向哪个控制器。

例如,要创建 GET 请求路由,它将如下所示:

routes/web.py

from masonite.routes import Get

Get('/url', 'Controller@method')

我们稍后再谈控制器。

您可以在 路由 文档中阅读有关路由的更多信息

创建我们的路由:

我们将首先创建一个视图和控制器来创建一篇博客文章。

控制器是一个包含控制器方法的简单类。这些控制器方法将成为我们的路由所调用的方法,因此它们将包含应用程序的所有业务逻辑。

如果您了解 Django 框架,可以将控制器方法看作 views.py 文件中的函数

现在让我们创建第一条路由。我们可以将所有路由放在 routes/web.pyROUTES 列表中。你会看到我们有一个主页的路由。让我们添加一个创建博客的路径。

routes/web.py

ROUTES = [
    Get('/', 'WelcomeController@show').name('welcome'),

    # 博客的路由
    Get('/blog', 'BlogController@show')
]

你会注意到这里有一个 BlogController@show 字符串。这意味着「使用blog控制器的 show 方法来呈现这个路由」。这里唯一的问题是我们还没有博客控制器。

让我们在下一步中创建 BlogController第2部分-创建我们的第一个控制器

创建控制器

所有控制器都位于 app/http/controllers 目录中, Masonite 为每个文件升级一个控制器。这对于更大的应用程序开发是有效的,因为大多数开发人员使用具有高级搜索功能的文本编辑器,如 Sublime 、 VSCode 或 Atom 。在这个实例中,在类之间切换很简单,可以促进更快的开发。很容易记住控制器的确切位置,因为文件名就是控制器。

当然,您可以随意移动控制器,但 craft 命令行工具将默认将它们放在单独的文件中。如果你觉得这很奇怪的话,不妨试试看你是否喜欢这种固执的布局。

创建我们的第一个控制器

像 Masonite 的大多数部分一样,您可以使用 craft 命令构建控制器:

$ craft controller Blog

这将在 app/http/controllers 目录中创建一个如下所示的控制器:

app/http/controller/BlogController.py

""" BlogController 模块。"""

from masonite.request import Request
from masonite.view import View
from masonite.controllers import Controller

class BlogController(Controller):
    """ BlogController 控制器类"""

    def __init__(self, request: Request):
        """ BlogController 初始化程序

        参数:
            request {masonite.request.Request} -- Masonite 请求类。
        """
        self.request = request

    def show(self, view: View):
        pass

很简单,对吧?你会注意到我们在寻找一个 show 方法。这些称为「控制器方法」,类似于 Django 所说的「视图」

但也要注意,我们现在有了前面在路由中指定的show方法。

返回视图

我们可以在控制器中返回很多不同的东西,但是现在我们可以从控制器返回一个视图。 Masonite 中的视图是 html 文件或「模板」。它们本身不像其他 Python 框架那样是 Python 对象。视图是用户将看到(或查看)的内容。

这很重要,因为这是我们对 Python 的 IOC 容器的第一次介绍。我们在参数列表中指定我们需要一个视图类, Masonite 将为我们注入它。

现在我们不再关注整个控制器,而只关注我们担心的部分。 ... 意味着在代码之间有一些我们不担心的东西:

app/http/controllers/BlogController.py

from masonite.view import View 
...
def show(self, view: View):
    return view.render('blog')

注意这里我们「提示」了 View 类。这就是 Masonite 所说的「自动解析依赖注入」。如果你现在不明白,别担心。你读得越多,你就越能理解。

一定要了解更多关于服务容器的信息。

创建我们的视图

现在您会注意到,我们正在返回 blog 视图,但它还不存在。

所有视图都在 resources/templates 目录中。我们可以创建一个名为 resources/templates/blog.html 的新文件,也可以使用另一个 craft 命令:

$ craft view blog

这将为我们创建上述模板。

我们可以在这个文件中添加一些文本,如:

resources/templates/blog.html

这是一个博客

然后运行服务器

$ craft serve

打开 http://localhost:8000/blog 。你将在你的浏览器中看到「这是一个博客」。

身份验证

大多数应用程序都需要某种形式的身份验证。 Masonite 附带了一个 craft 命令,可以为您构建一个身份验证系统。这通常应该在新安装的 Masonite 上运行,因为它将为您创建控制器路由和视图。

对于我们的博客,我们需要设置某种形式的注册,以便我们可以让新用户开始发布文章到我们的博客。我们可以通过运行 craft 命令创建身份验证系统:

$ craft auth

我们应该会得到一个成功的消息,说明创建了一些新资产。你可以检查你的 controllers 文件夹,你应该会看到一些新的控制器,它们应该可以处理注册。

我们将稍后检查为我们创建的内容。

数据库设置

为了注册这些用户,我们需要一个数据库。希望您已经有了某种本地数据库设置,如 MySQL 或 Postgres ,但我们假设您没有。在这种情况下,我们可以使用SQLite。

现在我们需要更改一些环境变量,以便Masonite可以创建SQLite数据库。

这些环境变量可以在根目录的.env文件中找到。打开该文件,您可以看到如下内容:

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=masonite
DB_USERNAME=root
DB_PASSWORD=root

继续更改这些连接设置,方法是将sqlite添加到DB_CONNECTION变量,以及将要在迁移时为您创建的数据库中添加的任何内容。我们将其称为blog.db

.env

DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog.db
DB_USERNAME=root
DB_PASSWORD=root

迁移

设置正确的凭据后,我们可以继续迁移数据库。开箱即用,Masonite具有一个针对users表的迁移,它将成为我们用户的基础。您可以在迁移之前编辑,但是默认配置可以更好地满足大多数需求,您以后可以随时添加或删除。

$ craft migrate

这将为我们创建用户表以及迁移表,以跟踪我们以后添加的所有迁移。

创建用户

现在我们已经有了身份验证和所有迁移,现在让我们创建第一个用户。请记住,我们运行了craft auth,所以我们有一些新的模板和控制器。

继续运行服务器:

$ craft serve

然后转到 localhost:8000/register 并填写表单。您可以使用您喜欢的任何名称和电子邮件,但为此目的,我们将使用:

Username: demo
Email: demo@email.com
Password: password

迁移

既然我们已经设置了身份验证,并且已经适应了迁移,那么让我们创建一个新的迁移来存储我们的帖子。

我们的 posts 表应该有几个明显的列,我们将在本教程中简化这些列。让我们来看看我们是如何用 Masonite 创造迁移的。

Craft 命令

毫不奇怪,我们有一个 craft 命令来创建迁移。您可以阅读更多关于 数据库迁移 的信息,但我们会将其简化为命令,并解释一些正在发生的事情:

$ craft migration create_posts_table --create posts

这个命令只是创建迁移的开始,迁移将创建 posts 表。按照惯例,表名应该是复数的(模型名应该是单数,后面会详细介绍)。

这将在 databases/migrations 文件夹中创建迁移。让我们打开它,从第6行开始,我们应该会看到这样的东西:

databases/migrations/2018_01_09_043202_create_posts_table.py

def up(self):
    """
    运行迁移。
    """
    with self.schema.create('posts') as table:
        table.increments('id')
        table.timestamps()

让我们在 posts 表中添加一个标题、一个作者和一个主体。

databases/migrations/2018_01_09_043202_create_posts_table.py

def up(self):
    """
    运行迁移。
    """
    with self.schema.create('posts') as table:
        table.increments('id')
        table.string('title')

        table.integer('author_id').unsigned()
        table.foreign('author_id').references('id').on('users')

        table.string('body')
        table.timestamps()

这应该很简单,但如果您想了解更多,请务必阅读[数据库迁移](orator-orm/ Database -migration .md)文档。

现在我们可以 migrate 这个迁移来创建 posts 表

$ craft migrate

模型

现在我们已经完成了表和迁移,并有了posts表,接下来创建一个模型。

Masonite 中的模型与其他 Python 框架稍有不同。 Masonite 使用 Orator ,这是 ORM 的一个积极的记录实现。这基本上意味着我们不会构建我们的模型,然后将其转化为迁移。模型和迁移在 Masonite 中是分开的。不管表是什么样子的,我们的模型都将形成表的形状。

创建我们的模型

同样,我们可以使用 craft 命令创建模型:

$ craft model Post

注意我们的模型用的是单数形式。默认情况下, Orator 会在我们的数据库(在本例中为 posts )中检查类的复数名称,方法是在模型中添加一个「s」。我们稍后将讨论如何显式地指定表。

创建的模型位于在 app/Post.py 中。当我们打开它时,它应该是这样的:

app/Post.py

""" Post 数据库模型。"""
from config.database import Model

class Post(Model):
    pass

很简单,对吧?如前所述,我们不必操纵模型。在创建或更改迁移时,模型将形成表的形状。

表名

同样,模型所附加的表名是模型\的复数形式(通过添加“s” ),但是如果您调用表,则可以使用诸如“ blog”而不是“ blogs”之类的其他名称,我们可以指定表名:

app/Post.py

"""A Post Database Model."""
from config.database import Model

class Post(Model):
    __table__ = 'blog'

批量分配

默认情况下,Orator可以防止批量分配,这是一项安全措施,因此我们需要明确设置希望填充的列:

app/Post.py

"""A Post Database Model."""
from config.database import Model

class Post(Model):
    __fillable__ = ['title', 'author_id', 'body']

关系

这种关系在这里很简单。请记住,我们在迁移中创建了外键。我们可以在模型中创建该关系,如下所示:

app/Post.py

"""A Post Database Model."""
from config.database import Model
from orator.orm import belongs_to

class Post(Model):
    __fillable__ = ['title', 'author_id', 'body']

    @belongs_to('author_id', 'id')
    def author(self):
        from app.User import User
        return User

由于Masonite的建模方式,某些模型可能会相互依赖,因此最好像上述那样在关系内执行导入,以防止任何可能的循环导入。

我们不会在这里详细介绍不同类型的关系,如要了解更多信息,请阅读ORM文档。

设计我们的博客

让我们创建一个HTML模板,以便我们可以进一步了解视图的工作方式。在这一部分中,先创建一个基本模板,当我们学到足够的HTML基础知识后,您可以继续并创建一个非常出色的博客模板(或从Internet上收集一个)。

现在我们有了模型和迁移设置,也拥有了页面布局和更新博客文章所需的所有后端。

我们还将在创建模板之前检查用户是否已登录。

创建模板

创建的URL将位于/ blog / create,一个简单的博客文章模板:

resources/templates/blog.html

<form action="/blog/create" method="POST">
    {{ csrf_field }}

    <input type="name" name="title">
    <textarea name="body"></textarea>
</form>

请注意,这里要填写 {{csrf_field}}。 Masonite带有CSRF保护,因此我们需要使用CSRF字段来渲染一个令牌。

现在,因为我们的posts表中有一个外键,所以我们需要确保用户在创建前已登录,让我们稍微修改一下模板:

resources/templates/blog.html

{% if auth() %}
    <form action="/blog/create" method="POST">
        {{ csrf_field }}

        <label> Title </label>
        <input type="name" name="title"><br>

        <label> Body </label>
        <textarea name="body"></textarea>

        <input type="submit" value="Post!">
    </form>
{% else %}
    <a href="/login">Please Login</a>
{% endif %}

auth()是一个视图辅助函数,它要么返回当前用户,要么返回None

Masonite 使用 Jinja2 模板, 如果您对这个模板引擎还不熟悉, 阅读 Jinja2 模板 文档

静态文件

为了简单起见,我们不去使用类似 Bootstrap 美化我们的博客。但是了解 Masonite 如何引入诸如 CSS 文件之类的静态文件是非常有必要的。接下来我们逐步了解如何添加 CSS 文件到我们的博客中。

首先,进入 storage/static/ 目录创建 blog.css 文件,并在文件内添加任何您喜欢的样式。 在这里,我们将 html 页面显示为灰色。

storage/static/blog.css

html {
    background-color: #ddd;
}

现在我们在模板文件顶部引入该文件。

resources/templates/blog.html

<link href="/static/blog.css" rel="stylesheet">
{% if auth() %}
    <form action="/blog/create" method="POST">
        {{ csrf_field }}

        <label> Title </label>
        <input type="name" name="title"><br>

        <label> Body </label>
        <textarea name="body"></textarea>

        <input type="submit" value="Post!">
    </form>
{% else %}
    <a href="/login">Please Login</a>
{% endif %}

静态文件引入非常简单,了解它们的工作原理非常重要。在本教程中,我们将重点放在后端。

Javascript 文件引入也类似:

resources/templates/blog.html

<link href="/static/blog.css" rel="stylesheet">
{% if auth() %}
    <form action="/blog/create" method="POST">
        {{ csrf_field }}

        <label> Title </label>
        <input type="name" name="title"><br>

        <label> Body </label>
        <textarea name="body"></textarea>

        <input type="submit" value="Post!">
    </form>
{% else %}
    <a href="/login">Please Login</a>
{% endif %}

<script src="/static/script.js"></script>

关于静态文件的更多知识,参考 静态文件

用于创建的控制器和容器

请注意,我们的操作将跳转到 /blog/create ,因此我们需要将路由定向到我们的控制器方法。在这个教程中,我们会将其定向到 store 方法。

我们打开 routes/web.py 文件并创建一个路由,将其添加到 ROUTES 列表:

routes/web.py

from masonite.routes import Get, Post
...

Post('/blog/create', 'BlogController@store'),

并在我们的控制器上创建一个 store 方法:

app/http/controllers/BlogController.py

...
def show(self, view: View): 
    return view.render('blog')

# New store Method
def store(self): 
    pass

从上面的表单中可以看到,我们将接受两个表单输入:title 和 body 。因此,让我们导入 Post 模型并使用输入数据创建一篇文章。

app/http/controllers/BlogController.py

from app.Post import Post
from masonite.request import Request
...

def store(self, request: Request):
    Post.create(
        title=request.input('title'),
        body=request.input('body'),
        author_id=request.user().id
    )

    return 'post created'

请注意,我们现在在此处使用了request:Request。这是Request对象。这个是从哪里来的?这是 Masonite 的强大和美妙之处,也是对 服务容器 的首次介绍。 服务容器 是一种非常强大的实现,因为它允许您向 Masonite 询问对象(在这种情况下为 Request )并获取该对象。这是一个重要的概念,因此请务必进一步阅读文档。

在此处阅读有关[服务容器]的更多信息(architectural-concepts / service-container.md)。

请注意这里我们使用了Input()方法。Masonent不区分请求方法,因此是否使用GETPOST请求并不重要。您可以始终使用此方法。

继续使用craft serve运行服务器,然后转到http://localhost:8000/blog并创建帖子。这里应该使用post请求方法到/blog/create路径,我们应该看到“post Created”。

显示我们的帖子

让我们继续并展示如何显示我们刚刚创建的帖子。在本部分中,我们将创建2个新模板来显示所有帖子和特定帖子。

创建模板

让我们创建2个新模板。

$ craft view posts
$ craft view single

让我们从显示所有帖子开始

创建控制器

让我们创建一个新控制器,以将其与BlogController分开。

$ craft controller Post

因此,现在在我们的show方法中,我们将显示所有帖子,然后创建一个single的方法来显示特定的帖子。

显示方法

show方法中返回包含所有帖子的帖子视图:

app/http/controllers/PostController.py

from app.Post import Post

...

def show(self, view: View):
    posts = Post.all()

    return view.render('posts', {'posts': posts})

帖子路由

我们需要为此方法添加路由:

routes/web.py

Get('/posts', 'PostController@show')

路由视图

我们的文章视图非常简单:

resources/templates/posts.html

{% for post in posts %}
    {{ post.title }}
    <br>
    {{ post.body }}
    <hr>
{% endfor %}

继续运行服务器,然后访问 http://localhost:8000/posts 链接。您应该可以看到文章的列表。如果只看到一个,那去 http://localhost:8000/blog 去创建更多内容吧。

显示作者

我们之前创建了作者和文章的关系。Oator 将采用这种关系并建立属性,因此我们可以显示作者的姓名:

resources/templates/posts.html

{% for post in posts %}
    {{ post.title }} by {{ post.author.name }}
    <br>
    {{ post.body }}
    <hr>
{% endfor %}

接下来让我们重复这个过程,稍微改变一下来实现单篇文章展示。

单篇文章

接下来,我们只显示一篇文章。我们需要新增一个路由:

routes/web.py

Get('/post/@id', 'PostController@single')

请注意这里有一个 @id 字符串。我们将会在下一部分在控制器中获取URL部分使用它。

Single 方法

让我们创建一个 single 方法来显示单篇文章。

app/http/controllers/PostController.py

from app.Post import Post
from masonite.request import Request
from masonite.view import View
...

def single(self, view: View, request: Request):
    post = Post.find(request.param('id'))

    return view.render('single', {'post': post})

我们使用 param() 方法从URL中获取 id 。这个 id 就是上面我们在路由中指定的 @id

在项目里,我们一般会用类似 @slug 的操作 ,然后用 request().param('slug') 获取。

单篇文章展示

现在只需要显示一篇文章,所以我们写一个简单的视图文件即可:

resources/templates/single.html

{{ post.title }}
<br>
{{ post.body }}
<hr>

运行服务器,并访问 http://localhost:8000/post/1http://localhost:8000/post/2 ,将会看到不同的文章。

更新和删除文章

目前为止,我们花费了一些时间来讨论上面的逻辑。接下来让我们快速完成更新和删除文章。我们假设您已经掌握了上面的知识,这部分的内容大同小异。

更新方法

让我们在 PostController 文件里新增更新方法。

app/http/controllers/PostController.py

def update(self, view: View, request: Request):
    post = Post.find(request.param('id'))

    return view.render('update', {'post': post})

def store(self, request: Request):
    post = Post.find(request.param('id'))

    post.title = request.input('title')
    post.body = request.input('body')

    post.save()

    return 'post updated'

我们已经对控制器比较熟悉,所以一次性写了两个方法 updatestore 。我们用 update 方法来展示一个表单,用 store 实现更新入库。

创建视图文件

$ craft view update

resources/templates/update.html

<form action="/post/{{ post.id }}/update" method="POST">
    {{ csrf_field }}

    <label for="">Title</label>
    <input type="text" name="title" value="{{ post.title }}"><br>

    <label>Body</label>
    <textarea name="body">{{ post.body }}</textarea><br>

    <input type="submit" value="Update">
</form>

创建路由

我们新增了两个控制器方法,现在将它们附加到路由文件中。

routes/web.py

Get('/post/@id/update', 'PostController@update'),
Post('/post/@id/update', 'PostController@store'),

就是这样!现在,我们可以更新我们的文章了。

删除方法

让我们更进一步,新增一个 delete 方法。

app/http/controllers/PostController.py

from masonite.request import Request
...

def delete(self, request: Request):
    post = Post.find(request.param('id'))

    post.delete()

    return 'post deleted'

删除路由

routes/web.py

Get('/post/@id/delete', 'PostController@delete'),

注意为了简单起见,我们在这里使用了 GET 路由,使用 POST 方法会更好。我们在更新页面上添加一个链接,该链接将删除该文章。

更新模板

我们可以在更新模板中直接添加一个删除链接:

resources/templates/update.html

<form action="/post/{{ post.id }}/update" method="POST">
    {{ csrf_field }}

    <label for="">Title</label>
    <input type="text" name="title" value="{{ post.title }}"><br>

    <label>Body</label>
    <textarea name="body">{{ post.body }}</textarea><br>

    <input type="submit" value="Update">

    <a href="/post/{{ post.id }}/delete"> Delete </a>
</form>

太棒了!现在,您有了一个博客,可用于创建,查看,更新和删除帖子!继续探索吧!

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

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

原文地址:https://learnku.com/docs/masonite/2.3/cr...

译文地址:https://learnku.com/docs/masonite/2.3/cr...

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


暂无话题~