Preface
Today we will build a simple news release system. The first stage of the system does not need to be too difficult. It mainly has the following functions
① News type management
② News management (with picture upload function)
③ News browsing
Although there are not many functions, it also covers many basic operations. The program is only added, deleted, checked and modified, and it is enough to add and upload attachments. So let's start our study today
Preparation
After yesterday's trouble, we already have nodeJS and mongoDB environments. Now we can directly create new project files and database files
The first step is to open the command character and switch to D disk to enter
Copy the code as follows: D:/>express -e news
So the system will automatically build the basic environment happily
It is obvious that many modules do not have dependencies. At this time, I will directly take yesterday's package.json:
The code copy is as follows:
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.4.8",
"ejs": "*",
"mongodb": "*"
}
}
Then switch to the project directory:
Copy the code as follows: nmp install
All dependencies are completed, and then we enter
The code copy is as follows:
D:/news>node app
Express server listening on port 3000
So, our program started running happily. When we opened the URL, we found that there was no problem.
PS: There is a problem here that needs to be noted. The file we downloaded is not UTF-8 encoding, so there may be garbled code in Chinese, and the file encoding needs to be unified by everyone.
When the program starts running, it requires database-related configuration
① First create a new news folder in the mongoDB directory
② Add configuration file settings.js to the project
The code copy is as follows:
module.exports = {
cookieSecret: 'myNews',
db: 'news',
host: 'localhost'
};
③ Create a new model directory and create a new db.js
The code copy is as follows:
var settings = require('../settings'),
Db = require('mongodb').Db,
Connection = require('mongodb').Connection,
Server = require('mongodb').Server;
module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_PORT), { safe: true });
④ Create a new news.bat program on the desktop
Copy the code as follows:d:/mongodb/bin/mongod.exe -dbpath d:/mongodb/news
In the future, we need to start the database, just run it. In this way, our preliminary preparations are basically over.
But there are two more annoying things here. One is that it is very annoying to start the news program every time, and the other is that you need to restart when modifying anything. So let’s solve these two problems first.
① Create news_app.bat on the desktop, and then run it to start the program.
Copy the code as follows: node d:/news/app
② Supervisor is a process protector. We can use it to help us restart the program, first follow, and then adjust our node_app.bat
Copy the code as follows: supervisor d:/news/app
Of course, you need to install it before:
Copy the code as follows: npm install -g supervisor
After this, you don’t need to restart manually after modifying the file (news_app needs to be placed in the project directory), so the preparations are over here
Project structure
After the first step is over, we need to think about the project structure
① Home page is index, and all news types and news entries will be listed here
② Each news item has three buttons for editing/deleting/viewing
③ The home page has a news button (pictures can be uploaded when adding)
Basic functions are as above
So, we remove the routing function in the app and put all the routes into the index
The code copy is as follows:
//Put the routing function into index
//app.get('/', routes.index);
//app.get('/users', user.list);
routes(app);
The code copy is as follows:
module.exports = function (app) {
//Home page, now also home page
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
app.get('/add', function (req, res) {
res.send('Add news request');
});
app.get('/delete', function (req, res) {
res.send('Delete News Request');
});
app.get('/view', function (req, res) {
res.send('View news request');
});
app.get('/update', function (req, res) {
res.send('Modify news request');
});
};
The first step is simple, because there should be a separate page for adding news, and clicking the add button will cause other processing, so the internal request must be subdivided. The following regulations are now as follows:
/ Default page, which displays all types as well as news, with a delete button
/add to add news page
/addNews Add news specific post request address (response when clicking the button)
/delete Delete News Request
/view specific news inquiry
So slightly modify the above route:
The code copy is as follows:
module.exports = function (app) {
//Home page, now also home page
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
app.get('/add', function (req, res) {
res.send('Add news page');
});
app.post('/addNews', function (req, res) {
res.send('handle add news request');
});
app.get('/delete', function (req, res) {
res.send('Delete News Request');
});
app.get('/view', function (req, res) {
res.send('View news request');
});
};
So we need to create several new templates to organize our web pages. Here we don’t separate the first and last pages.
Add two template files add and view, which temporarily performs consistent with index.ejs, and is related to navigation modification
The code copy is as follows:
module.exports = function (app) {
//Home page, now also home page
app.get('/', function (req, res) {
res.render('index', { title: 'Express' });
});
app.get('/add', function (req, res) {
res.render('add', { title: 'Add News Page' });
});
app.post('/addNews', function (req, res) {
res.send('handle add news request');
});
app.get('/delete', function (req, res) {
res.send('Delete News Request');
});
app.get('/view', function (req, res) {
res.render('view', { title: 'View news request' });
});
};
The project structure ends
Data operation
After the overall structure comes out, we need to perform data operations:
① Add data (add news)
② Display data (display news)
③ Delete data (delete news)
It originally involved type operations, but it was done and it was gone. Don't care about it for the time being, because it's easy to get confused when doing it for the first time.
Add news
Here, we don't use form submission, we use ajax... Here we introduce the zepto library, so our page becomes like this
The code copy is as follows:
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="javascripts/zepto.js" type="text/javascript"></script>
</head>
<body>
<h1>
<%= title %></h1>
<div>
Title: <input type="text" id="title" />
</div>
<div>
Content: <textarea id="content"></textarea>
</div>
<div>
<input type="button" type="button" id="ok" value="Add news" />
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#ok').click(function () {
var param = {};
param.title = $('#title').val();
param.content = $('#content').val();
$.post('/addNews', param, function () {
console.log('Added successfully');
});
});
});
</script>
</body>
</html>
Although there is no request response program yet, the data will not be processed, and there is no attachment here (the attachment is only allowed for one), so I modified the code and added the picture:
PS: The more troublesome thing is that the image is a bit troublesome after ajax processing, so let's just switch back to form operations here, otherwise how long will it take to do it...
The code copy is as follows:
<html>
<head>
<title>
<%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>
<%= title %></h1>
<form enctype="multipart/form-data" method="post" action="/addNews">
<div>
Title: <input type="text" id="title" name="title" />
</div>
<div>
Picture: <input type="file" id="pic" name="pic" />
</div>
<div>
Content: <textarea id="content" name="content"></textarea>
</div>
<div>
<input type="submit" id="ok" value="Add news" />
</div>
</form>
</body>
</html>
There is no need to consider the attachment issue too much. Let's do it for now. Now we will process the request program first. Here we will create a new news folder in public to store its pictures.
model
Add a new news.js file to the models folder, build an entity for it, and give new query-related operations:
The code copy is as follows:
var mongodb = require('./db');
function News(title, content, pic) {
this.title = title;
this.content = content;
this.pic = pic;//Save the storage path
};
module.exports = News;
//Storage data
News.prototype = {
save: function (callback) {
var date = new Date();
var time = {
date: date,
year: date.getFullYear(),
month: date.getFullYear() + "-" + (date.getMonth() + 1),
day: date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(),
minute: date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " +
date.getHours() + ":" + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
}
//Data storage object
var news = {
title: this.title,
content: this.content,
pic: this.pic, // Finally, when it comes to image processing, save it first
time: time
};
//Open the data connection, opening it is a callback...
mongodb.open(function (err, db) {
//Exit if the error is wrong
if (err) {
return callback(err);
}
//Open the news collection
db.collection('news', function (err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
//Write to the collection (write to the database)
collection.insert(news, { safe: true }, function (err) {
return callback(err);
});
callback(null);//err is null
});
});
}
};
So, there is a program to write to the database. Here we will try to insert the database. Of course, we need to modify the program at the routing office.
PS: Of course, the routing cannot write too much logical code, this file must be separated in the future
At this time the logic in /addNews needs to be changed
The code copy is as follows:
app.post('/addNews', function (req, res) {
var title = req.body.title;
var content = req.body.content;
var pic = req.body.pic;
var news = new News(title, content, pic)
news.save(function (err, data) {
res.send(data);
})
});
After querying, there is no big problem, now the attachment problem is the problem
Upload pictures
The uploading function of express itself supports it. Express parses the request body through bodyParser, and then uploads the file through it. It uses formatable internally.
Here, change the app.use(express.bodyParser()) in app.js to:
The code copy is as follows: app.use(express.bodyParser({ keepExtensions: true, uploadDir: './public/news' }));
Open index.js and add a line of code in front of it:
Copy the code as follows: fs = require('fs'),
Modify the index file:
The code copy is as follows:
app.post('/addNews', function (req, res) {
for (var i in req.files) {
if (req.files[i] == 0) {
//Delete a file in synchronization
fs.unlinkSync(req.files[i].path);
console.log('success removed an empty file');
} else {
var path = './public/news/' + req.files[i].name;
// Rename a file using synchronous method
fs.renameSync(req.files[i].path, path);
console.log('sunccess renamed a file');
}
}
// var title = req.body.title;
// var content = req.body.content;
// var pic = req.body.pic;
// var news = new News(title, content, pic)
// news.save(function (err, data) {
// res.send(data);
// })
});
At this time, after selecting the file, click Add News, and our file will be uploaded
At this time, I just need to record the file name in the database, and there are pictures in the file directory
The code copy is as follows:
app.post('/addNews', function (req, res) {
var pic = null;
for (var i in req.files) {
if (req.files[i] == 0) {
//Delete a file in synchronization
fs.unlinkSync(req.files[i].path);
console.log('success removed an empty file');
} else {
var path = './public/news/' + req.files[i].name;
// Rename a file using synchronous method
fs.renameSync(req.files[i].path, path);
console.log('sunccess renamed a file');
}
pic = req.files[i].name;
}
var title = req.body.title;
var content = req.body.content;
var news = new News(title, content, pic)
news.save(function (err, data) {
res.send(data);
})
res.send('<a href="./">Request succeeds, return to homepage</a>');
});
There is data in the database, and our directory also has files. Now we only need to read the data out.
PS: The brothers urged me to go out for a drink during the holiday
Read data
The second step is of course reading the data, and the first is reading the data on the home page:
The code copy is as follows:
var mongodb = require('./db');
function News(title, content, pic) {
this.title = title;
this.content = content;
this.pic = pic;//Save the storage path
};
module.exports = News;
//Storage data
News.prototype = {
save: function (callback) {
var date = new Date();
//Data storage object
var news = {
title: this.title,
content: this.content,
pic: this.pic, // Finally, when it comes to image processing, save it first
date: date
};
//Open the data connection, opening it is a callback...
mongodb.open(function (err, db) {
//Exit if the error is wrong
if (err) {
return callback(err);
}
//Open the news collection
db.collection('news', function (err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
//Write to the collection (write to the database)
collection.insert(news, { safe: true }, function (err) {
return callback(err);
});
callback(null); //err is null
});
});
}
};
//Read articles and related information
News.get = function (id, callback) {
//Open the database
mongodb.open(function (err, db) {
if (err) {
return callback(err);
}
db.collection('news', function (err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
var query = {};
if (id) {
query.id = id;
}
//Query articles based on query object
collection.find(query).sort({
date: -1
}).toArray(function (err, data) {
mongodb.close();
if (err) {
return callback(err); //Failed! Return to err
}
callback(null, data); //Success! Return the result of the query as an array
});
});
});
};
news.js
The code copy is as follows:
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1>
<%= title %></h1>
<ul>
<%for(var k in data) { %>
<li>
<div>
Title: <%=data[k].title %></div>
<div>
Content: <%=data[k].content%></div>
<div>
Attachment: <img src="news/<%= data[k].pic%>" /></div>
</div>
<div>
<a href="/delete?id=<%=data[k] %>">Delete</a>
</div>
<hr/>
</li>
<%} %>
</ul>
</body>
</html>
Conclusion
Okay, let’s stop here for the production of the article publishing system. In the future, we will gradually add functions and beautify them.