在URL路由中使用object:title而不是:id

时间:2014-02-08 06:17:48

标签: node.js express mongoose

更新:请参阅下面的答案,了解最终解决方案

我有一个具有唯一标题名称的对象,我想在路线中使用标题而不是整个网站的ID。

routes.js

// Current routing

var articles = require('../app/controllers/articles')

app.param('articleId', articles.load)
app.get('/articles', articles.index)
app.get('/articles/new', articles.new)
app.post('/articles', articles.create)
app.get('/articles/:articleId', articles.show)
app.get('/articles/:articleId/edit', articles.edit)
app.put('/articles/:articleId', articles.update)
app.del('/articles/:articleId', articles.destroy)

***

// Desired routing

app.param('articleTitle', articles.load)
app.get('/articles', articles.index)
app.get('/articles/new', articles.new)
app.post('/articles', articles.create)
app.get('/articles/:articleTitle', articles.show)
app.get('/articles/:articleTitle/edit', articles.edit)
app.put('/articles/:articleTitle', articles.update)
app.del('/articles/:articleTitle', articles.destroy)

articles.js(Controller)

exports.load = function(req, res, next, title){
  Article.load(title, function (err, article) {
    if (err) return next(err)
    if (!article) return next(new Error('not found'))
    req.article = article
    next()
  })
}

exports.show = function(req, res){
  res.render('articles/show', {
    title: req.article.title,
    article: req.article
  })
}

article.js(模特)

ArticleSchema.statics = {
  load: function (title, cb) {
    this.findOne({ title : title })
      .exec(cb)
  }
}

基本上,我已经对任何id引用进行了分析,并用标题引用替换它们。出于某种原因,他们根本就没有工作。

示例将转到网址http://localhost:3000/articles/test而不是http://localhost:3000/articles/5TheId234,这不起作用,抛出此错误:GET / articles / test 404 148ms

提前致谢!

2 个答案:

答案 0 :(得分:1)

当你发布这个问题时,也许这只是一个复制和粘贴错误,但我注意到你的新路由有一个拼写错误(应该是articles.new):

app.get('/articles/new', rticles.new)

我想知道是否可能导致某些路线覆盖其他路线的路线排序。但我创建了一个简单的测试,似乎工作正常。

正如您所看到的,您可以看到以下相同的路线,它的工作方式与预期完全相同。解开这个并看一看?也许这可以为您缩小问题范围。

var express = require('express');
var app = express();


var articles = [
    {id: 1, title: 'tagtreetv_rocks', 
        link: 'http://localhost:3000/articles/tagtreetv_rocks'
    },
    {id: 2, title: 'tagtreetv_launches', 
        link: 'http://localhost:3000/articles/tagtreetv_launches'
    }
];


app.param('articleTitle', function(req, res, next, title){
    var article = articles.filter(function(a){return a.title == title;});   
    if (!article) return next(new Error('not found'));
    req.article = article;
    next();
});

app.get('/articles/new', function(req, res){
    res.json({
        id: '?',
        title: '?'
    });
});

app.get('/articles', function(req, res){
    res.json(articles); 
});

app.post('/articles', function(req, res){
    articles.push(req.body);
    res.send(200);
});

app.get('/articles/:articleTitle', function(req, res){
    res.json(req.article);
});

app.get('/articles/:articleTitle/edit', function(req, res){
    res.json(req.article);
});



app.listen(3000);
console.log('Listening on port 3000');

顺便说一下,如果你对全栈JavaScript编程感兴趣,我最近推出了一些关于这个主题的截屏视频:http://tagtree.tv

答案 1 :(得分:0)

这是一个数据错误,但我通过根据输入标题创建和使用单独的url字段改进了我的初始结构:

<强> routes.js

var articles = require('../app/controllers/articles')

app.param('articleURL', articles.load)
app.get('/articles', articles.index)
app.get('/articles/new', articles.new)
app.post('/articles', articles.create)
app.get('/articles/:articleURL', articles.show)
app.get('/articles/:articleURL/edit', articles.edit)
app.put('/articles/:articleURL', articles.update)
app.del('/articles/:articleURL', articles.destroy)

articles.js(Controller)

exports.create = function (req, res) {
  var article = new Article(req.body)

  // Builds URL by removing spaces
  // note: url is a hidden field in the form
  // replaces spaces with underscores
  // removes all special characters (not '_')
  // converts to lowercase
  // to shorten the length, use 'substring(0,18)' - 18 char max example
  article.url = sport.title.replace(/ /g,'_').replace(/\W/g,'').toLowerCase() 

  article.uploadAndSave(req.files.image, function (err) {
    if (!err) {
      req.flash('success', 'Successfully created article!')
      return res.redirect('/article/'+article.url)
    }
    res.render('articles/new', {
      title: 'New Article',
      sport: article,
      errors: utils.errors(err.errors || err)
    })
  })
}

exports.load = function(req, res, next, title){
  Article.load(title, function (err, article) {
    if (err) return next(err)
    if (!article) return next(new Error('not found'))
    req.article = article
    next()
  })
}

exports.show = function(req, res){
  res.render('articles/show', {
    title: req.article.title,
    article: req.article
  })
}

article.js(模特)

ArticleSchema.statics = {
  load: function (url, cb) {
    this.findOne({ url : url })
      .exec(cb)
  }
}