Express. js ошибка приложения: в качестве идентификатора поста используется название категории - PullRequest
0 голосов
/ 06 мая 2020

Я работаю над приложением для ведения блога (щелкните ссылку, чтобы увидеть репозиторий GitHub ) с Express, E JS и 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); конфликтуют таким образом, что отдельные сообщения больше не отображаются .

Это потому, что идентификаторы сообщений берутся для маршрутов категорий.

В контроллере у меня есть 2 метода 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>

Я хотел бы исправить эту проблему, сохранив шаблон http://localhost:3000/category-name для URL-адресов, отображающих сообщения в категориях.

Как этого добиться?

Ответы [ 2 ]

2 голосов
/ 06 мая 2020

Если для вас важно сохранить шаблон 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.

Единственное, что вам нужно сделать, это заменить req.params.catname и req.params.id на req.params.param внутри обоих методов вашего файла postsController.

Вы также можете удалить проверку совпадения метод getSinglePost, поскольку он реализован в файле маршрута.

2 голосов
/ 06 мая 2020

На самом деле это один и тот же маршрут:

// 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);
...