javascript CastError:对于模型“Campground”的路径“_id”处的值{{Campground.name}}(类型字符串),转换为ObjectID失败

g52tjvyc  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(63)
const express = require("express");
const session = require("express-session");
const cookieParser = require('cookie-parser')

const mongoose = require("mongoose");
const { Campground, User, Review } = require("./modules/mainModule")

const ejs = require("ejs");
const ejsMate = require('ejs-mate');

const Joi = require("joi");
const flash = require("connect-flash");

const path = require("path");
const bodyParser = require("body-parser");

const methodOverride = require("method-override");
const customError = require("./public/javascript/customError");
const catchAsync = require("./public/javascript/catchAsync");
const { validateCampground } = require("./schemas");

const campgroundRoute = require("./routes/campgrounds");

const app = express();
app.set("view engine", "ejs");
app.set("views", path.join(\__dirname, "/views"));

app.engine("ejs", ejsMate);

app.use(express.urlencoded({ extended: true }))
app.use(bodyParser.json());
app.use('/public', express.static(\__dirname + '/public'));

app.use(methodOverride('\_method'));

mongoose.connect('mongodb://localhost:27017/campdb')
.then(() =\> {
console.log("Mongoose connected");
})
.catch((err) =\> {
console.log("ERROR!");
console.log(err);
})

const sessionConfig = {
secret: "super",
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: true,
expires: Date.now() + 1000 \* 60 \* 60 \* 24 \* 7,
maxAge: 1000 \* 60 \* 60 \* 24 \* 7
}
}

app.use(session(sessionConfig));
app.use(cookieParser());
app.use(flash());

app.get("/", catchAsync(async (req, res, next) =\> {
let i = 0;
const features = \[\];
while (i != 5) {
const feature = await Campground.findOne({ rating: 5 });
features.push(feature);
i++;
}

    res.render("index.ejs", { features });

}))

app.use((req, res, next) =\> {
res.locals.success = req.flash("success");
res.locals.error = req.flash("error");
next();
})

app.use("/campgrounds", campgroundRoute);

app.get("/about", (req, res) =\> {
res.render("about");
})

app.get("/contacts", (req, res) =\> {
res.render("contacts");
})

app.use((err, req, res, next) =\> {
const { message = "wazaaa", statusCode = 500 } = err;

    res.status(statusCode).send(message);

})

app.listen("8080", () =\> {

    console.log("Listening on port 8080");

})
const express = require("express");
const router = express.Router({ mergeParams: true });
const flash = require("connect-flash");

const path = require("path");
const bodyParser = require("body-parser");

const { Campground, User, Review } = require("../modules/mainModule")
const customError = require("../public/javascript/customError");
const catchAsync = require("../public/javascript/catchAsync");
const { validateCampground } = require("../schemas");
const app = express();



router.get("/", async (req, res) => {
    const foundCampgrounds = await Campground.find({});
    res.render("campgrounds", { foundCampgrounds });
})

router.get("/:id", async (req, res) => {
    const campground = await Campground.findById(req.params.id).populate("reviews");
    res.render("campground", { campground });
})

router.post("/", async (req, res) => {

    const campground = await new Campground({ ...req.body.campground });
    await campground.save();
    req.flash("success", "You have created a campground");
    res.redirect(`campgrounds/${campground._id}`);
})

router.get("/new", async (req, res) => {
    res.render("new");
})

router.post("/:id", async (req, res) => {
    const campground = await Campground.findById(req.params.id);
    const review = await new Review({ comment: `${req.body.campground.comment}`, rating: req.body.campground.rating });

    campground.reviews.push(review);
    await review.save();
    await campground.save();

    res.redirect(`/campgrounds/${campground._id}`);
})

router.put("/:id", async (req, res) => {
    const { id } = req.params;
    await Campground.findByIdAndUpdate(id, { ...req.body.campground });
    res.redirect(`/campgrounds/${id}`);
})

router.delete("/:id", async (req, res) => {
    const campground = await Campground.findById(req.params.id).populate();
    for (let review of campground.reviews) {
        await Review.findByIdAndDelete(review._id);
    }

    campground.delete();
    res.redirect("/campgrounds");
})

router.delete("/:id/:id2", async (req, res) => {
    const { id, id2 } = req.params;
    await Campground.findByIdAndUpdate(id, { $pull: { reviews: id2 } });
    await Review.findByIdAndDelete(id2);
    res.redirect(`/campgrounds/${id}`);
})

router.get("/:id/edit", async (req, res) => {
    const campground = await Campground.findById(req.params.id);
    res.render("edit", { campground });
})

module.exports = router;
const mongoose = require("mongoose");

const campgroundSchema = new mongoose.Schema({

    name: {
        type: String,
        required: true

    },

    price: {
        type: Number,
        required: true,
        min: 0
    },

    description: {
        type: String,
        // required: true
    },

    image: {
        type: String
    },

    location: {
        type: String,
        // required: true
    },

    owner: {
        type: String,
        // required: true
    },

    contacts: {
        type: String,
        // required: true
    },

    ratings: {
        type: Number
    },

    reviews: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: "review"
        }
    ]

})

const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true
    },

    password: {
        type: String,
        required: true
    },

    email: {
        type: String,
        required: true
    }
})

const reviewSchema = new mongoose.Schema({
    username: {
        type: String,
        default: ""
    },

    comment: {
        type: String,
        required: true
    },

    rating: {
        type: Number,
        min: 0,
        max: 5,
        required: true
    }
})

const Campground = mongoose.model("Campground", campgroundSchema);
const User = mongoose.model("User", userSchema);
const Review = mongoose.model("review", reviewSchema);

module.exports = { Campground, User, Review };`

在我“/”获取路径中,我列出了我的露营地。我已经种了一堆。在这里,我可以点击露营地的名称,它会把我带到“/:id”获取路线。我可以刷新页面,一切正常,ID在链接中。
在我的“/”get路由中,我有一个到“/new”的链接,在那里我可以创建一个新的露营地。它创建并通常重定向到露营地获取路由“/:id”。现在如果我重新加载页面,我会得到这个错误和一个“出错”页面。我也得到这个错误,如果我试图访问露营地从得到“/”路线,它产生的错误让我到露营地页面,但再次给我一个“出了问题”的页面后,重新加载。
当我查看这个错误时,我真的很困惑为什么要获取campground.name值并试图将其转换为ObjectId。为什么它甚至加载页面摆在首位,然后不。
我检查了数据库和露营地是有和所有它的值都在地方,因为他们应该是。
真的很困惑
编辑:
露营地列表ejs:

<%- include("../views/parts/head.ejs"); %>

    <body>

        <%- include ('./parts/navbar.ejs'); %>

            <p>
                <%= success %>
            </p>

            <form action="/campgrounds/new" method="get">
                <button>Create Campground</button>
            </form>

            <main>
                <% for(let el of foundCampgrounds) { %>
                    <div>
                        <h3>
                            <a href="campgrounds/<%= el._id %>">
                                <%= el.name %>
                            </a>
                        </h3>
                        <p>
                            <%= el.description %>
                        </p>
                        <table>

                            <tr>
                                <td>
                                    <%= el.location %>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <%= el.price %>
                                </td>
                                <td>
                                    <%= el.ratings %>
                                </td>
                            </tr>

                        </table>
                    </div>

                    <% } %>
            </main>
            <%- include("../views/parts/footer.ejs"); %>
    </body>

    </html

具体营地EJS:

<%- include("../views/parts/head.ejs"); %>

    <body class="bg-white txt-black">

        <%- include("./parts/navbar_yellow.ejs"); %>

            <%= success %>

                <div>
                    <h3>
                        <%= campground.name %>
                    </h3>
                    <p>
                        <%= campground.description %>
                    </p>

                    <p>
                        <img src="<%= campground.image %>" alt="">
                    </p>
                    <table>
                        <tr>
                            <td>
                                <%= campground.owner %>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <%= campground.location %>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <%= campground.contacts %>
                            </td>
                        </tr>
                        <tr>
                            <td>
                                <%= campground.price %>
                            </td>
                            <td>
                                <%= campground.ratings %>
                            </td>
                        </tr>
                    </table>

                    <a href="/campgrounds/<%= campground._id %>/edit">Edit Campground</a>
                    <a href="/campgrounds">All Campgrounds</a>
                    <form action="/campgrounds/<%= campground._id%>?_method=DELETE" method="post">
                        <button>Delete Campground</button>
                    </form>

                    <% if(campground.reviews) { %>
                        <% for(let review of campground.reviews) { %>
                            <div>
                                <h3>
                                    <% if(review.username) { %>

                                        <%= review.username %>

                                            <% } else {%>
                                                Bazooka
                                                <% } %>
                                </h3>
                                <p>
                                    <%= review.comment %>
                                </p>
                                <div>
                                    <span>5/<%= review.rating%></span>
                                </div>
                                <form action="<%= campground._id %>/<%= review._id %>?_method=DELETE" method="post">
                                    <button>Delete</button>
                                </form>
                            </div>
                            <% } %>
                                <% } %>


                                    <div>
                                        <h1>
                                            <%= campground.name %>
                                        </h1>

                                        <form action="<%= campground._id %>" method="post">

                                            <label for="comment">Comment:</label>
                                            <br>
                                            <input type="text" name="campground[comment]"
                                                placeholder="This place is the best!" required>

                                            <label for="rating">Rating:</label>
                                            <input type="number" name="campground[rating]" min="0" max="5" required>

                                            <button>Submit</button>
                                        </form>
                                    </div>
                </div>
                <%- include("../views/parts/footer.ejs"); %>
    </body>

    </html>
ia2d9nvy

ia2d9nvy1#

尝试检查浏览器发送的确切GET请求。对我来说,这个错误的原因是图像数据库中的一些dummy_image数据。在img标记中使用src="dummy_image"会导致浏览器向/dummy_image发送GET请求,该请求被.get("/:id")路由捕获,使用"dummy_image"作为id的值。
代码中的另一个问题是.get("/:id")路由应该在其他get路由的下面。否则,它也会捕获像"/new"这样的请求,并将new用作id,从而在查询数据库时导致相同的CastError

**一般要点:**在查询DB之前,最好检查id

if (mongoose.Types.ObjectId.isValid(id)) {
    const campground = await Campground.findById(req.params.id).populate("reviews");
    res.render("campground", { campground });
}
else {
    res.status(404).send(`Got invalid ID: ${id}`);
}

相关问题