Express.js 应用程序错误:类别名称被用作 post id
Express.js application bug: category name is taken for post id
我正在研究 blogging application (click the link to see the GitHub repo) with Express, EJS 和 MongoDB。
我有帖子,它们被分为类别,每个类别都有自己的集合。
我按类别过滤帖子:运动类别中的所有帖子显示在http://localhost:3000/sport
,旅游中的所有帖子] 类别显示在 http://localhost:3000/travel
.
为此我引入了路线 router.get('/:catname', postsController.getPostsByCategory);
:
const express = require('express');
const postsController = require('../../controllers/front-end/posts');
// Express router
const router = express.Router();
// Get Posts
router.get('/', postsController.getPosts);
// Get Posts by Category
router.get('/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/:id', postsController.getSinglePost);
module.exports = router;
类别确实按类别过滤,但是 router.get('/:catname', postsController.getPostsByCategory);和 router.get('/:id', postsController.getSinglePost);
之间存在冲突,因此 不再显示单个帖子。
那是因为帖子ID被用于类别路由。
在控制器中我有两种方法 getPostsByCategory
和 getSinglePost
:
exports.getPostsByCategory = async (req, res, next) => {
function titleize(slug) {
var words = slug.split("-");
return words.map(function(word) {
return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
}).join(' ');
}
const postCategory = new RegExp(titleize(req.params.catname),"ig");
const singleCategory = await Category.findOne({cat_name:postCategory})
const posts = await Post.find({ category : singleCategory }, (err, posts) => {
if (err) {
console.log('Error: ', err);
} else {
res.render('default/index', {
moment: moment,
layout: 'default/layout',
website_name: 'MEAN Blog',
page_heading: 'XPress News',
page_subheading: 'A MEAN Stack Blogging Application',
posts: posts.reverse(),
});
}
}).populate('category');
};
exports.getSinglePost = (req, res, next) => {
let id = req.params.id;
if (id.match(/^[0-9a-fA-F]{24}$/)) {
Post.findById(id, function(err, post) {
if (err) {
console.log('Error: ', err);
} else {
res.render('default/singlepost', {
layout: 'default/layout',
website_name: 'MEAN Blog',
post: post
});
}
});
}
};
在我拥有的(所有)帖子的视图中:
<p class="post-meta">Posted in <a href="/<%= post.category.cat_name.replace(/\s+/g, '-').toLowerCase(); %>"><%= post.category.cat_name %></a>, on <%= moment(post.created_at).format( 'MMM-DD-YYYY') %></p>
我想解决此问题的方式是保持按类别显示帖子的 URL 的模式 http://localhost:3000/category-name
。
我怎样才能做到这一点?
其实这两条路线是一样的:
// Get Posts by Category
router.get('/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/:id', postsController.getSinglePost);
我建议创建不同的路线,例如:
// Get Posts by Category
router.get('/category/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/post/:id', postsController.getSinglePost);
如果按类别保持单个 post 和 post 的模式 http://localhost:3000/:param
对您很重要,您可以只使用一种路由方法处理两个请求
// This will handle Get requests both for Posts by Category and single Post
router.get('/:param', (req, res, next) => {
// If :param is Mongo ObjectId call the getSinglePost method.
if (req.params.param.match(/^[0-9a-fA-F]{24}$/)) {
postsController.getSinglePost(req, res, next);
}
else {
postsController.getPostsByCategory(req, res, next);
}
});
我刚刚添加了一个中间件,它检查请求参数。如果它是 ObjectId 类型,则调用 getSinglePost 方法,否则调用 getPostsByCategory 方法。
您唯一需要做的就是在 postsController
文件的两个方法中用 req.params.param
替换 req.params.catname
和 req.params.id
。
你也可以去掉getSinglePost方法中的匹配检查,因为它是在路由文件中实现的。
我正在研究 blogging application (click the link to see the GitHub repo) with Express, EJS 和 MongoDB。
我有帖子,它们被分为类别,每个类别都有自己的集合。
我按类别过滤帖子:运动类别中的所有帖子显示在http://localhost:3000/sport
,旅游中的所有帖子] 类别显示在 http://localhost:3000/travel
.
为此我引入了路线 router.get('/:catname', postsController.getPostsByCategory);
:
const express = require('express');
const postsController = require('../../controllers/front-end/posts');
// Express router
const router = express.Router();
// Get Posts
router.get('/', postsController.getPosts);
// Get Posts by Category
router.get('/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/:id', postsController.getSinglePost);
module.exports = router;
类别确实按类别过滤,但是 router.get('/:catname', postsController.getPostsByCategory);和 router.get('/:id', postsController.getSinglePost);
之间存在冲突,因此 不再显示单个帖子。
那是因为帖子ID被用于类别路由。
在控制器中我有两种方法 getPostsByCategory
和 getSinglePost
:
exports.getPostsByCategory = async (req, res, next) => {
function titleize(slug) {
var words = slug.split("-");
return words.map(function(word) {
return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
}).join(' ');
}
const postCategory = new RegExp(titleize(req.params.catname),"ig");
const singleCategory = await Category.findOne({cat_name:postCategory})
const posts = await Post.find({ category : singleCategory }, (err, posts) => {
if (err) {
console.log('Error: ', err);
} else {
res.render('default/index', {
moment: moment,
layout: 'default/layout',
website_name: 'MEAN Blog',
page_heading: 'XPress News',
page_subheading: 'A MEAN Stack Blogging Application',
posts: posts.reverse(),
});
}
}).populate('category');
};
exports.getSinglePost = (req, res, next) => {
let id = req.params.id;
if (id.match(/^[0-9a-fA-F]{24}$/)) {
Post.findById(id, function(err, post) {
if (err) {
console.log('Error: ', err);
} else {
res.render('default/singlepost', {
layout: 'default/layout',
website_name: 'MEAN Blog',
post: post
});
}
});
}
};
在我拥有的(所有)帖子的视图中:
<p class="post-meta">Posted in <a href="/<%= post.category.cat_name.replace(/\s+/g, '-').toLowerCase(); %>"><%= post.category.cat_name %></a>, on <%= moment(post.created_at).format( 'MMM-DD-YYYY') %></p>
我想解决此问题的方式是保持按类别显示帖子的 URL 的模式 http://localhost:3000/category-name
。
我怎样才能做到这一点?
其实这两条路线是一样的:
// Get Posts by Category
router.get('/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/:id', postsController.getSinglePost);
我建议创建不同的路线,例如:
// Get Posts by Category
router.get('/category/:catname', postsController.getPostsByCategory);
// Get Single Post
router.get('/post/:id', postsController.getSinglePost);
如果按类别保持单个 post 和 post 的模式 http://localhost:3000/:param
对您很重要,您可以只使用一种路由方法处理两个请求
// This will handle Get requests both for Posts by Category and single Post
router.get('/:param', (req, res, next) => {
// If :param is Mongo ObjectId call the getSinglePost method.
if (req.params.param.match(/^[0-9a-fA-F]{24}$/)) {
postsController.getSinglePost(req, res, next);
}
else {
postsController.getPostsByCategory(req, res, next);
}
});
我刚刚添加了一个中间件,它检查请求参数。如果它是 ObjectId 类型,则调用 getSinglePost 方法,否则调用 getPostsByCategory 方法。
您唯一需要做的就是在 postsController
文件的两个方法中用 req.params.param
替换 req.params.catname
和 req.params.id
。
你也可以去掉getSinglePost方法中的匹配检查,因为它是在路由文件中实现的。