javascript MVC模式- Node.js Express和MongoDB Web应用程序

tyg4sfes  于 2022-11-20  发布在  Java
关注(0)|答案(1)|浏览(105)

I'm developing a Nde.js Express & MongoDB web application.
I'm trying to use the MVC pattern to improve my website.
However, after creating a model, I can't access some pages and I get the following error message on my terminal:
TypeError: C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\home\posts.ejs:19 17| 18| <% for (const post of posts) { %>
19|

  • <%- include('includes/posts/post-item', { post: post }) %> 20| <% } %> 21| 22| <% } %>

C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\home\includes\posts\post-item.ejs:4 2| " alt="" /> 3|

<%= post.title %>

4| By <%= post.author.name %>
5|
<%= post.summary %>
6| 7| ">View Post
Cannot read properties of undefined (reading 'name') at eval ("C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\home\includes\posts\post-item.ejs":20:38) at post-item (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:703:17) at include (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:701:39) at eval ("C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\home\posts.ejs":29:17) at posts (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:703:17) at tryHandleCache (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:274:36) at View.exports.renderFile [as engine] (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\ejs\lib\ejs.js:491:10) at View.render (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\view.js:135:8) at tryRender (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\application.js:657:10) at Function.render (C:\Users\DELL\Desktop\node-com4muz-database-mvc\node_modules\express\lib\application.js:609:3) { path: 'C:\Users\DELL\Desktop\node-com4muz-database-mvc\views\home\posts.ejs' }
I would like someone to help me find where is the issue in my code by comparing both versions: before the MVC pattern and after the MVC pattern.

Before the MVC pattern:
routes\admin\blog.js from line 37 to line 62:

const express = require('express');
const mongodb = require('mongodb');
const multer = require('multer');

const storageConfig = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'public/admin/images');
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname);
  }
});

const db = require('../../data/database');

const ObjectId = mongodb.ObjectId;

const upload = multer({ storage: storageConfig });

const router = express.Router();

router.get('/posts', async function (req, res) {
  const posts = await db
    .getDb()
    .collection('posts')
    .find({})
    .project({ title: 1, summary: 1, 'author.name': 1 })
    .toArray();
  res.render('posts-list', { posts: posts });
});

router.get('/new-post', async function (req, res) {
  const authors = await db.getDb().collection('authors').find().toArray();
  res.render('create-post', { authors: authors });
});

router.post('/new-post', upload.single('image'), async function (req, res) {
  const uploadedImageFile = req.file;

  const authorId = new ObjectId(req.body.author);
  const author = await db
    .getDb()
    .collection('authors')
    .findOne({ _id: authorId });

  const newPost = {
    title: req.body.title,
    summary: req.body.summary,
    body: req.body.content,
    date: new Date(),
    author: {
      id: authorId,
      name: author.name,
      email: author.email
    },
    imagePath: uploadedImageFile.path
  };

  const result = await db.getDb().collection('posts').insertOne(newPost);
  // console.log(result);
  res.redirect('/posts');
});

router.get('/blog/:id/edit', async function (req, res) {
  const postId = req.params.id;
  const post = await db
    .getDb()
    .collection('posts')
    .findOne({ _id: new ObjectId(postId) }, { title: 1, summary: 1, body: 1 });

  if (!post) {
    return res.status(404).render('404');
  }

  res.render('update-post', { post: post });
});

router.post('/blog/:id/edit', async function (req, res) {
  const postId = new ObjectId(req.params.id);
  const result = await db
    .getDb()
    .collection('posts')
    .updateOne(
      { _id: postId },
      {
        $set: {
          title: req.body.title,
          summary: req.body.summary,
          body: req.body.content
          // date: new Date()
        }
      }
    );

  res.redirect('/posts');
});

router.post('/blog/:id/delete', async function (req, res) {
  const postId = new ObjectId(req.params.id);
  const result = await db
    .getDb()
    .collection('posts')
    .deleteOne({ _id: postId });
  res.redirect('/posts');
});

router.get('/admin', async function (req, res) {
  if (!res.locals.isAuth) {
    // if (!req.session.user)
    return res.status(401).render('401');
  }

  if (!res.locals.isAdmin) {
    return res.status(403).render('403');
  }

  res.render('admin');
});

module.exports = router;

After the MVC pattern:
routes\admin\blog.js from line 69 to line 72:

const express = require('express');
const mongodb = require('mongodb');
const multer = require('multer');

const storageConfig = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'public/admin/images');
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname);
  }
});

const db = require('../../data/database');

const Post = require('../../models/post');

const ObjectId = mongodb.ObjectId;

const upload = multer({ storage: storageConfig });

const router = express.Router();

router.get('/posts', async function (req, res) {
  const posts = await db
    .getDb()
    .collection('posts')
    .find({})
    .project({ title: 1, summary: 1, 'author.name': 1 })
    .toArray();
  res.render('posts-list', { posts: posts });
});

router.get('/new-post', async function (req, res) {
  const authors = await db.getDb().collection('authors').find().toArray();
  res.render('create-post', { authors: authors });
});

router.post('/new-post', upload.single('image'), async function (req, res) {
  const uploadedImageFile = req.file;

  const authorId = new ObjectId(req.body.author);
  const author = await db
    .getDb()
    .collection('authors')
    .findOne({ _id: authorId });

  const enteredTitle = req.body.title;
  const enteredSummary = req.body.summary;
  const enteredContent = req.body.content;
  const date = new Date();
  const selectedAuthor = {
    author: {
      id: authorId,
      name: author.name,
      email: author.email
    }
  };
  const selectedImage = uploadedImageFile.path;

  const post = new Post(
    enteredTitle,
    enteredSummary,
    enteredContent,
    date,
    selectedAuthor,
    selectedImage
  );
  await post.save();

  res.redirect('/posts');
});

router.get('/blog/:id/edit', async function (req, res) {
  const postId = req.params.id;
  const post = await db
    .getDb()
    .collection('posts')
    .findOne({ _id: new ObjectId(postId) }, { title: 1, summary: 1, body: 1 });

  if (!post) {
    return res.status(404).render('404');
  }

  res.render('update-post', { post: post });
});

router.post('/blog/:id/edit', async function (req, res) {
  const postId = new ObjectId(req.params.id);
  const result = await db
    .getDb()
    .collection('posts')
    .updateOne(
      { _id: postId },
      {
        $set: {
          title: req.body.title,
          summary: req.body.summary,
          body: req.body.content
          // date: new Date()
        }
      }
    );

  res.redirect('/posts');
});

router.post('/blog/:id/delete', async function (req, res) {
  const postId = new ObjectId(req.params.id);
  const result = await db
    .getDb()
    .collection('posts')
    .deleteOne({ _id: postId });
  res.redirect('/posts');
});

router.get('/admin', async function (req, res) {
  if (!res.locals.isAuth) {
    // if (!req.session.user)
    return res.status(401).render('401');
  }

  if (!res.locals.isAdmin) {
    return res.status(403).render('403');
  }

  res.render('admin');
});

module.exports = router;

Indeed, I have created a model to use the post route where I create new post. Here is the code I wrote:

models\post.js:

const db = require('../data/database');

class Post {
  constructor(title, summary, content, date, author, image, id) {
    this.title = title;
    this.summary = summary;
    this.content = content;
    this.date = date;
    this.autor = author;
    this.image = image;
    this.id = id; // may be undefined
  }

  async save() {
    const newPost = {
      title: this.title,
      summary: this.summary,
      content: this.content,
      date: this.date,
      author: this.author,
      imagePath: this.image
    };

    const result = await db.getDb().collection('posts').insertOne(newPost);
    // console.log(result);
    return result;
  }
}

module.exports = Post;

Before, I changed the code from the first version before the MVC pattern, the website was working fine.
Now, the error says that post.author.name in views\home\includes\posts\post-item.ejs is not defined anymore.
Please find the code related to view the blog page:

views\home\posts.ejs:

<!DOCTYPE html>
<html lang="en">
  <head>
    <%- include('../admin/includes/head', { title: 'Blog - Tous Les Articles' })
    %>
    <link rel="stylesheet" href="/admin/styles/posts.css" />
  </head>

  <body>
    <%- include('../admin/includes/header') %>
    <main id="all-posts">
      <h1>Nos Articles</h1>
      <% if (!posts || posts.length === 0) { %>
      <p>Aucun article trouvé - peut-être voulez-vous en créer un ?</p>
      <a class="btn" href="/new-post">Create a new Post</a>
      <% } else { %>
      <ol id="posts-list">
        <% for (const post of posts) { %>
        <li><%- include('includes/posts/post-item', { post: post }) %></li>
        <% } %>
      </ol>
      <% } %>
    </main>
  </body>
</html>

views\home\includes\posts\post-item.ejs:

<article class="post-item">
  <img src="<%= post.imagePath %>" alt="<%= post.title %>" />
  <h2><%= post.title %></h2>
  <p class="post-item-author">By <%= post.author.name %></p>
  <p><%= post.summary %></p>
  <div class="post-actions">
    <a class="btn" href="/blog/<%= post._id %>">View Post</a>
  </div>
</article>
oxiaedzo

oxiaedzo1#

我通过调用selectedAuthor常量上的author对象修复了这个问题,如下第28行所示:

router.post('/new-post', upload.single('image'), async function (req, res) {
  const uploadedImageFile = req.file;

  const authorId = new ObjectId(req.body.author);
  const author = await db
    .getDb()
    .collection('authors')
    .findOne({ _id: authorId });

  const enteredTitle = req.body.title;
  const enteredSummary = req.body.summary;
  const enteredContent = req.body.content;
  const date = new Date();
  const selectedAuthor = {
    author: {
      id: authorId,
      name: author.name,
      email: author.email
    }
  };
  const selectedImage = uploadedImageFile.path;

  const post = new Post(
    enteredTitle,
    enteredSummary,
    enteredContent,
    date,
    selectedAuthor.author,
    selectedImage
  );
  await post.save();

  res.redirect('/posts');
});

相关问题