此子文档显示,如何定义页面以删除Author对象。

正如表单设计部分所讨论的那样,我们的策略是,只允许删除 “未被其他对象引用” 的对象(在这种情况下,这意味着如果作者Author被一本书Book引用,我们将不允许删除作者)。在实现方面,这意味着,表单需要在删除作者之前,先确认没有关联的书籍。如果存在关联的书籍,则应显示它们,并说明在删除Author对象之前,必须删除它们。

控制器—get 路由

打开/controllers/authorController.js。找到导出的author_delete_get() 控制器方法,并将其替换为以下代码。

// Display Author delete form on GET.
exports.author_delete_get = function(req, res, next) {

    async.parallel({
        author: function(callback) {
            Author.findById(req.params.id).exec(callback)
        },
        authors_books: function(callback) {
          Book.find({ 'author': req.params.id }).exec(callback)
        },
    }, function(err, results) {
        if (err) { return next(err); }
        if (results.author==null) { // No results.
            res.redirect('/catalog/authors');
        }
        // Successful, so render.
        res.render('author_delete', { title: 'Delete Author', author: results.author, author_books: results.authors_books } );
    });

};

控制器从URL参数(req.params.id)中,获取要删除的Author实例的 id。它使用async.parallel() 方法,并行获取作者记录和所有相关书本。当两个操作都完成后,它将呈现author_delete.pug视图,为titleauthor、和 author_books传递变量。

注意: 如果findById()返回“没有结果”,则作者不在数据库中。在这种情况下,没有什么可以删除,所以我们立即呈现所有作者的列表。

}, function(err, results) {
    if (err) { return next(err); }
    if (results.author==null) { // No results.
        res.redirect('/catalog/authors')
    }

控制器—post 路由

找到导出的author_delete_post()控制器方法,并将其替换为以下代码。

// Handle Author delete on POST.
exports.author_delete_post = function(req, res, next) {

    async.parallel({
        author: function(callback) {
          Author.findById(req.body.authorid).exec(callback)
        },
        authors_books: function(callback) {
          Book.find({ 'author': req.body.authorid }).exec(callback)
        },
    }, function(err, results) {
        if (err) { return next(err); }
        // Success
        if (results.authors_books.length > 0) {
            // Author has books. Render in same way as for GET route.
            res.render('author_delete', { title: 'Delete Author', author: results.author, author_books: results.authors_books } );
            return;
        }
        else {
            // Author has no books. Delete object and redirect to the list of authors.
            Author.findByIdAndRemove(req.body.authorid, function deleteAuthor(err) {
                if (err) { return next(err); }
                // Success - go to author list
                res.redirect('/catalog/authors')
            })
        }
    });
};

首先,我们验证是否已提供id(这是通过表单主体参数发送的,而不是使用URL中的版本)。然后我们以与GET路由相同的方式,获得作者及其相关书本。如果没有书本,那么我们删除作者对象,并重定向到所有作者的列表。如果还有书本,那么我们只需重新呈现表格,传递作者和要删除的书本列表。

注意: 我们可以检查对findById()的调用,是否返回任何结果,如果没有,则立即呈现所有作者的列表。为简洁起见,我们将代码保留在上面(如果找不到id,它仍会返回作者列表,但这将在findByIdAndRemove()之后发生)。

视图

创建 /views/author_delete.pug 并复制贴上底下文字。

extends layout

block content
  h1 #{title}: #{author.name}
  p= author.lifespan
  
  if author_books.length
  
    p #[strong Delete the following books before attempting to delete this author.]
  
    div(style='margin-left:20px;margin-top:20px')

      h4 Books
    
      dl
      each book in author_books
        dt 
          a(href=book.url) #{book.title}
        dd #{book.summary}

  else
    p Do you really want to delete this Author?
    
    form(method='POST' action='')
      div.form-group
        input#authorid.form-control(type='hidden',name='authorid', required='true', value=author._id )

      button.btn.btn-primary(type='submit') Delete

视图扩展了布局模板,覆盖了名为content的区块。在顶部显示作者详细信息。然后它包含一个,基于author_booksifelse子句)数量的条件语句。

  • 如果存在与作者相关联的书本,则该页面列出书本,并说明在删除该作者Author之前,必须删除这些书籍。
  • 如果没有书本,则页面会显示确认提示。如果单击“删除”Delete按钮,则会在POST请求中,将作者ID发送到服务器,并且将删除该作者的记录。

加入一个删除控制器

接下来,我们将向 Author 详细视图添加 Delete 控件(详细信息页面是删除记录的好地方)。

注意: 在完整实现中,控件将仅对授权用户可见。但是在这个时间点上,我们还没有一个授权系统!

打开 author_detail.pug 视图,并在底部添加以下行。

hr
p
  a(href=author.url+'/delete') Delete author

控件现在应显示为链接,如下面的作者详细信息页面所示。

它看起來像是?

运行应用程序,并将浏览器打开,到http://localhost:3000/。然后选择所有作者链接 All authors,然后选择一个特定作者。最后选择删除作者链接 Delete author。

如果作者没有书本,您将看到这样的页面。按删除后,服务器将删除作者并重定向到作者列表。

如果作者确实有书本,那么您将看到如下视图。然后,您可以从其详细信息页面中,删除这些书本(一旦该代码被实现!)。

注意: 其他删除对象的页面,可以用相同的方式实现。我们把它留下,作为挑战。

下一步

文档标签和贡献者

此页面的贡献者: edgar-chen
最后编辑者: edgar-chen,