在哪里可以找到我的代码中模型“项目”的路径“ _id”中值“创建”的Cast到ObjectId的源失败

时间:2019-08-01 12:56:20

标签: javascript node.js mongodb express mongoose

我正在按照MDN的Express.js教程为odin项目的Nodejs项目清单创建清单应用程序。我可以删除项目,更新项目和读取项目,但是当我要创建项目时,会遇到错误(对于模型“项目”,在路径“ _id”的值“创建”对ObjectId的转换失败)。

我仔细阅读了所有代码,当尝试替换“ items_create_get”中的内容时,错误从未改变,这使我认为这不是问题所在。

//itemsController.js:
var Items = require("../models/items");
var async = require("async");
const { body, validationResult } = require("express-validator/check");
const { sanitizeBody } = require("express-validator/filter");

exports.items_create_post = [
// Convert the category to an array.
(req, res, next) => {
if (!(req.body.category instanceof Array)) {
    if (typeof req.body.category === "undefined") 
        req.body.category = [];
    else req.body.category = new Array(req.body.category);
}
    next();
},

// Handle items create on POST.
exports.items_create_post = [
   // Convert the category to an array.
    (req, res, next) => {
        if (!(req.body.category instanceof Array)) {
            if (typeof req.body.category === "undefined") 
                req.body.category = [];
            else req.body.category = new Array(req.body.category);
        }
        next();
   },

// Validate fields.
body("name", "Name must not be empty.")
.isLength({ min: 1 })
.trim(),
body("description", "Description must not be empty.")
.isLength({ min: 1 })
.trim(),
body("price", "Price must not be empty.")
.isLength({ min: 1 })
.trim(),
body("num_in_stock", "Number in stock must not be empty")
.isLength({ min: 1 })
.trim(),

// Sanitize fields.
sanitizeBody("*").escape(),
sanitizeBody("category.*").escape(),
// Process request after validation and sanitization.
(req, res, next) => {
  // Extract the validation errors from a request.
  const errors = validationResult(req);

  // Create a Items object with escaped and trimmed data.
  var items = new Items({
    name: req.body.name,
    description: req.body.description,
    category: req.body.category,
    price: req.body.price,
    num_in_stock: req.body.num_in_stock
  });

  if (!errors.isEmpty()) {
    /* There are errors. Render form again with sanitized values/error messages.*/

  // Get all categories for form.
  async.parallel(
    {
      category: function(callback) {
        Category.find(callback);
      }
    },
    function(err, results) {
      if (err) {
        return next(err);
      }

      res.render("items_form", {
        title: "Create Item",
        category: results.category,
        items: items,
        errors: errors.array()
      });
    }
  );
  return;
} else {
  // Data from form is valid. Save book.
  items.save(function(err) {
    if (err) {
      return next(err);
    }
    // Successful - redirect to new items record.
    res.redirect(items.url);
  });
}
}
];

//items.js(Model):
var mongoose = require('mongoose');

var Schema = mongoose.Schema;

var ItemsSchema = new Schema ({
name: {type: String, required: true, max: 100},
description: {type: String, required: true},
category: {type: Schema.Types.ObjectId, ref: 'Category', required: true},
price: {type: String, required: true},
num_in_stock: {type: String, required: true}
})

ItemsSchema.virtual('url').get(function() {
     return '/catalog/items/' + this._id
});

module.exports = mongoose.model('Items', ItemsSchema);

//catalog.js (Router):

router.get('/items/create', items_controller.items_create_get);
router.post('/items/create', items_controller.items_create_post);

//items_form.pug(views):

extends layout

block content
    h1= title

    form(method='POST' action='')
        div.form-group
            label(for='name') Name:
            input#name.form-control(type='text', placeholder='Name of item' name='name' required='true' value=(undefined===items ? '' : items.name) )
        div.form-group
             label(for='description') Description:
             input#description.form-control(type='textarea', placeholder='Enter Description' name='description' value=(undefined===items ? '' : items.description) required='true' )
        div.form-group
            label(for='category') Category:
            input#category.form-control(type='text', placeholder='Consumable, Tools or Accessories' name='category' value=(undefined===items ? '' : items.category.name) required='true' )
        div.form-group
            label(for='price') Price:
            input#price.form-control(type='text', placeholder='Price: e.g. 20$' name='price' value=(undefined===items ? '' : items.price) required='true')
        div.form-group
            label(for='num_in_stock') Number in Stock:
            input#num_in_stock.form-control(type='text', placeholder='num in stock: e.g. 2' name='num_in_stock' value=(undefined===items ? '' : items.num_in_stock) required='true') 
        button.btn.btn-primary(type='submit') Submit 

    if errors 
        ul
            for error in errors
                li!= error.msg

//Edit: catalog.js (Router):
// GET catalog home page.
router.get('/', items_controller.index);
// GET request for one Item.
router.get('/items/:id', items_controller.items_detail);
// GET request for list of all Item.
router.get('/items', items_controller.items_list);
router.get('/items/create', items_controller.items_create_get);
router.post('/items/create', items_controller.items_create_post);
// GET request to delete Item.
router.get('/items/:id/delete', items_controller.items_delete_get);
// POST request to delete Item.
router.post('/items/:id/delete',
items_controller.items_delete_post);
// GET request to update Item.
router.get('/items/:id/update', items_controller.items_update_get);
// POST request to update Item.
router.post('/items/:id/update',
items_controller.items_update_post);

这个问题也在我的类别模型中...

输出屏幕很好,所有其他CRUD视图都可以使用create控制器之外的其他功能...也许值得一提的是,当我更新项目时,items_form.js可以完美地工作! * /

2 个答案:

答案 0 :(得分:0)

问题出在您的虚拟架构中,请尝试将其更改为:

ItemsSchema.virtual('url').get(function() {
     return '/catalog/items/' + this._id.toString()
});

这是因为_id的类型为 ObjectId ,而您正在尝试将其与字符串连接。

希望这会有所帮助:)

答案 1 :(得分:0)

因为您放:

router.get('/items/:id', items_controller.items_detail);

之前:

router.get('/items/create', items_controller.items_create_get);

因此,当您呼叫/items/create时,路由器将指向items_controller.items_detail,而不是items_controller.items_create_get,并获得create作为参数id

更改路由器,将/items/:id放在/items/create之后可能会解决您的问题。