1. 程式人生 > >【NodeJS 學習筆記04】新聞釋出系統

【NodeJS 學習筆記04】新聞釋出系統

前言

昨天,我們跟著這位大哥的部落格(https://github.com/nswbmw/N-blog/wiki/_pages)進行了nodeJS初步的學習,最後也能將資料插入資料庫了

但是一味的跟著別人部落格寫程式碼肯定不行,所以我們今天就來做一個簡單的新聞釋出系統,系統第一階段不需要太難,主要有以下功能

① 新聞型別管理

② 新聞管理(具有圖片上傳功能)

③ 新聞瀏覽

功能雖然不多,但是也涵蓋很多基本操作了,程式不過增刪查改嘛,外加上傳附件,夠了。於是開始我們今天的學習吧

準備工作

根據昨天的折騰後,我們已經有了nodeJS與mongoDB環境了,現在直接新建工程檔案與資料庫檔案即可

第一步,開啟命令符切換到D盤後輸入

D:\>express -e news

 於是系統會自動開開心心構建基本環境

很明顯,裡面很多模組依賴沒有,這個時候將昨天的package.json直接考過來:

{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.8",
    "ejs": "*",
    "mongodb": "*"
  }
}

然後切換到專案目錄下:

nmp install

依賴檔案全部搞下來了,然後我們輸入

D:\news>node app
Express server listening on port 3000

於是,我們的程式高高興興的執行起來了,開啟網址一看,確實沒問題

PS:這裡有個問題需要注意,我們下載下來的檔案不是UTF-8編碼,所以中文可能有亂碼,檔案編碼需要各位自己統一

程式跑起來了就需要資料庫相關的配置了

① 首先在mongoDB目錄中新建news資料夾

② 為專案新增配置檔案settings.js

module.exports = {
  cookieSecret: 
'myNews', db: 'news', host: 'localhost' };

③ 新建models目錄,新建db.js

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 });

④ 在桌面新建news.bat程式

d:\mongodb\bin\mongod.exe -dbpath d:\mongodb\news

以後要啟動資料庫,只需要執行他即可,如此,我們初步的準備工作基本結束

但是這裡有兩個比較煩的事情,一個是每次要啟動news程式很煩,二個是修改任何東西都需要重啟,於是我們這裡先解決這兩個問題

① 在桌面新建news_app.bat,以後執行他就可以啟動程式了

node d:\news\app

② supervisor為一程序保護程式,我們可以使用他幫我們重啟程式,首先按照,然後調整我們的node_app.bat

supervisor  d:\news\app

當然之前需要安裝:

npm install -g supervisor

這個樣子後,修改了檔案就不需要手動重啟了(需要將news_app放到專案目錄下),於是準備工作到此為止

專案結構

第一步結束後,我們就需要思考下專案結構了

① 首頁為index這裡將列出所有新聞型別以及對於新聞條目

② 各個新聞條目擁有編輯/刪除/檢視 三個按鈕

③ 首頁具有增加新聞按鈕(增加時候可上傳圖片)

基本功能如上

於是,我們去掉app裡面的路由功能,將路由全部放到index裡面

//將路由功能放入index
//app.get('/', routes.index);
//app.get('/users', user.list);
routes(app);
module.exports = function (app) {
  //主頁,現在也是首頁
  app.get('/', function (req, res) {
    res.render('index', { title: 'Express' });
  });

  app.get('/add', function (req, res) {
    res.send('增加新聞請求');
  });

  app.get('/delete', function (req, res) {
    res.send('刪除新聞請求');
  });

  app.get('/view', function (req, res) {
    res.send('檢視新聞請求');
  });

  app.get('/update', function (req, res) {
    res.send('修改新聞請求');
  });

};

第一步簡單如此,因為增加新聞應該有單獨的頁面,而具體點選增加按鈕又會有其他處理,所以內部還得細分各個請求,現在規定如下:

/ 預設頁面,該頁面顯示所有型別以及新聞,並帶有刪除按鈕

/add 進入新增新聞頁面

/addNews 新增新聞具體post請求地址(點選按鈕時候的響應)

/delete 刪除新聞請求

/view 具體新聞查詢

於是稍微修改下上述路由:

module.exports = function (app) {
  //主頁,現在也是首頁
  app.get('/', function (req, res) {
    res.render('index', { title: 'Express' });
  });

  app.get('/add', function (req, res) {
    res.send('新增新聞頁面');
  });

  app.post('/addNews', function (req, res) {
    res.send('處理新增新聞請求');
  });

  app.get('/delete', function (req, res) {
    res.send('刪除新聞請求');
  });

  app.get('/view', function (req, res) {
    res.send('檢視新聞請求');
  });

};

於是我們需要新建幾個模板組織我們的網頁,這裡我們先不分離頭尾只要最簡單的頁面即可

新增add與view兩個模板檔案,暫時表現與index.ejs一致,並且修改導航相關

module.exports = function (app) {
  //主頁,現在也是首頁
  app.get('/', function (req, res) {
    res.render('index', { title: 'Express' });
  });

  app.get('/add', function (req, res) {
    res.render('add', { title: '新增新聞頁面' });
  });

  app.post('/addNews', function (req, res) {
    res.send('處理新增新聞請求');
  });

  app.get('/delete', function (req, res) {
    res.send('刪除新聞請求');
  });

  app.get('/view', function (req, res) {
    res.render('view', { title: '檢視新聞請求' });

  });
};

至此專案結構結束

資料操作

整體結構出來後,我們就需要進行資料操作了:

① 增加資料(增加新聞)

② 展示資料(展示新聞)

③ 刪除資料(刪除新聞)

本來還涉及到型別操作的,但是做著做著給搞沒了,暫時不管他吧,因為首次做容易迷糊

增加新聞

這裡,我們就不使用表單提交了,我們用ajax......這裡順便引入zepto庫,於是我們的頁面成了這樣

<!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>
        標題:<input type="text" id="title" />
    </div>
    <div>
        內容:<textarea id="content"></textarea>
    </div>
    <div>
        <input type="button" type="button" id="ok" value="新增新聞" />
    </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('新增成功');
                });
            });
        });
    </script>
</body>
</html>

雖然現在還沒有請求響應程式,所以資料並不會被處理,另外我們這裡的附件也沒有(現在附件只允許一個好了),於是再修改下程式碼,加入圖片:

PS:比較麻煩的是圖片經過ajax處理有點麻煩,所以我們這裡乖乖的換回form操作算了,不然又要搞多久......

<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>
        標題:<input type="text" id="title" name="title" />
    </div>
    <div>
        圖片:<input type="file" id="pic" name="pic" />
    </div>
    <div>
        內容:<textarea id="content" name="content"></textarea>
    </div>
    <div>
        <input  type="submit" id="ok" value="新增新聞" />
    </div>
    </form>
</body>
</html>

這個樣子就不需要過多的考慮附件問題,先暫時如此吧,現在先處理請求程式,這裡先在public裡面新建news資料夾用於儲存其圖片

model

在models資料夾新增news.js檔案,為其構建實體,並賦予新增查詢相關操作:

var mongodb = require('./db');


function News(title, content, pic) {
  this.title = title;
  this.content = content;
  this.pic = pic;//儲存儲存路徑
};

module.exports = News;

//儲存資料
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())
    }

    //資料儲存物件
    var news = {
      title: this.title,
      content: this.content,
      pic: this.pic, //圖片處理最後來說,現在先亂存
      time: time
    };

    //開啟資料連線,開啟就是一個回撥......
    mongodb.open(function (err, db) {
      //錯誤就退出
      if (err) {
        return callback(err);
      }

      //開啟news集合
      db.collection('news', function (err, collection) {
        if (err) {
          mongodb.close();
          return callback(err);
        }

        //寫入集合(寫入資料庫)
        collection.insert(news, { safe: true }, function (err) {
          return callback(err);
        });
        callback(null);//err為null
      });
    });
  }
};
View Code

於是,寫入資料庫的程式就有了,這裡我們來試試能不能插入資料庫,當然需要修改路由處的程式

PS:路由處當然不能寫過多邏輯程式碼,這個檔案以後還得分離

這個時候/addNews裡面的邏輯需要改變

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);
  })
});

查詢下,問題不大,現在要解決的就是附件問題了

上傳圖片

上傳圖片功能express本身就支援了,express通過bodyParser解析請求體,然後便可通過他上傳檔案了,其內部使用了formidable

這裡將app.js裡面的app.use(express.bodyParser())改為:

app.use(express.bodyParser({ keepExtensions: true, uploadDir: './public/news' }));

開啟index.js,在前面加一行程式碼:

fs = require('fs'),

修改一下index檔案:

app.post('/addNews', function (req, res) {

  for (var i in req.files) {
    if (req.files[i] == 0) {
      //同步方式刪除一個檔案
      fs.unlinkSync(req.files[i].path);
      console.log('success removed an empty file');
    } else {
      var path = './public/news/' + req.files[i].name;
      // 使用同步方式重新命名一個檔案
      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);
//    })
});

這個時候選取檔案後點擊新增新聞,我們的檔案就上傳上去了

這個時候,我只需要將檔名記錄在資料庫即可,檔案目錄裡面就有圖片了

app.post('/addNews', function (req, res) {

  var pic = null;

  for (var i in req.files) {
    if (req.files[i] == 0) {
      //同步方式刪除一個檔案
      fs.unlinkSync(req.files[i].path);
      console.log('success removed an empty file');
    } else {
      var path = './public/news/' + req.files[i].name;
      // 使用同步方式重新命名一個檔案
      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="./">請求成功,返回首頁</a>');

});

資料庫中有資料了,我們目錄也有檔案了,現在只需要將資料讀出來了

PS:放假兄弟們催的凶,要出去喝酒了

讀取資料

第二步當然是讀取資料,首先是首頁的資料讀取:

 1 var mongodb = require('./db');
 2 
 3 
 4 function News(title, content, pic) {
 5   this.title = title;
 6   this.content = content;
 7   this.pic = pic;//儲存儲存路徑
 8 };
 9 
10 module.exports = News;
11 
12 //儲存資料
13 News.prototype = {
14   save: function (callback) {
15     var date = new Date();
16 
17     //資料儲存物件
18     var news = {
19       title: this.title,
20       content: this.content,
21       pic: this.pic, //圖片處理最後來說,現在先亂存
22       date: date
23     };
24 
25     //開啟資料連線,開啟就是一個回撥......
26     mongodb.open(function (err, db) {
27       //錯誤就退出
28       if (err) {
29         return callback(err);
30       }
31 
32       //開啟news集合
33       db.collection('news', function (err, collection) {
34         if (err) {
35           mongodb.close();
36           return callback(err);
37         }
38 
39         //寫入集合(寫入資料庫)
40         collection.insert(news, { safe: true }, function (err) {
41           return callback(err);
42         });
43         callback(null); //err為null
44       });
45     });
46   }
47   
48 };
49 
50 
51 //讀取文章及其相關資訊
52 News.get = function (id, callback) {
53   //開啟資料庫
54   mongodb.open(function (err, db) {
55     if (err) {
56       return callback(err);
57     }
58     db.collection('news', function (err, collection) {
59       if (err) {
60         mongodb.close();
61         return callback(err);
62       }
63       var query = {};
64       if (id) {
65         query.id = id;
66       }
67       //根據 query 物件查詢文章
68       collection.find(query).sort({
69         date: -1
70       }).toArray(function (err, data) {
71         mongodb.close();
72         if (err) {
73           return callback(err); //失敗!返回 err
74         }
75         callback(null, data); //成功!以陣列形式返回查詢的結果
76       });
77     });
78   });
79 };
news.js
<!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>
               標題: <%=data[k].title %></div>
            <div>
              內容:  <%=data[k].content%></div>
              <div>
              附件:<img src="news/<%= data[k].pic%>" /></div>
              </div>
              <div>
              <a href="/delete?id=<%=data[k] %>">刪除</a>
              </div>
              <hr/>
        </li>
        <%} %>
    </ul>
</body>
</html>

結語

今天,暫時 這樣,晚上有約要出去了,有點倉促

相關推薦

NodeJS 學習筆記04新聞釋出系統

前言 昨天,我們跟著這位大哥的部落格(https://github.com/nswbmw/N-blog/wiki/_pages)進行了nodeJS初步的學習,最後也能將資料插入資料庫了 但是一味的跟著別人部落格寫程式碼肯定不行,所以我們今天就來做一個簡單的新聞釋出系統,系統第一階段不需要太難,主要有以下功

Django2x 學習筆記 04centos7 部署Python3.7x+Django2x+nginx+uwsgi

# 安裝Python3.7.1和Django: yum install gcc-c++ yum install libxml* yum install wget python的安裝依賴包: yum groupinstall "Development&nbs

機器學習筆記04隨機梯度下降

梯度下降 梯度下降是一個尋找函式機值的方式,屬於最優化裡的基礎演算法,在低維度的情況下非常容易理解。 例如存在函式y=x2y=x^2y=x2存在導數dy=2x,若當前點在x=1點,設dx的步長為0.1。此時我們通過負梯度計算下一個x點xt+1=xt−2∗0.

Linux學習筆記3Contos7系統沒有ifconfig,route -n功能解決辦法

上期說到第一次開啟Contos7系統遇到的問題,也講到了Contos系統是最小安裝化安裝,沒有像Window那麼多圖形,不僅僅如此,裡面的一些ifconfig,route -n等這些查詢網路的功能命令也會沒有。這是Contos7一些比較新版的系統已經淘汰了。當然

Redis學習筆記慢查詢、pipeline、釋出訂閱、Bitmap、HyperLogLog、GEO

目錄 慢查詢 pipeline 釋出訂閱 Bitmap HyperLogLog GEO 慢查詢 生命週期 傳送命令 --> 排隊 --> 執行命令 --> 返回結

canvas學習筆記基本認識

基本認識 設置 supported eight -c 失真 ont 之前 上下 <canvas>標簽定義了一塊畫布,畫布可以在網頁中繪制2D和3D圖象,現在先學習如何繪制2D圖象,繪制3D圖象屬於WebGL的內容(也就是網頁版的OpenGL,3D圖形接口)。 屬

mysql學習筆記整理

結束 ant 出現次數 varchar 移動 desc cal direct 指定 /*mysql學習筆記整理*/ /*常用的數據庫操作對象*/ #庫的操作#創建#數據庫的創建USE mysql;CREATE DATABASE db_x;#刪除#刪除數據庫DROP

深度學習筆記1如何建立和確定模型正確性?如何優化模型?

近期看了吳恩達的一本書,關於如何建立和確定優化模型?裡面有個人認為需要學習的地方,故做筆記: 1.模型訓練一共有三個資料集:訓練集、開發集(驗證集)、測試集。開發集不能太小,通常在1000-10000,並且測試集屬於同一分佈;2.過擬合:訓練過程中開發集的準確率和測試集測試的準確率差別不大,若開發集比測試集

MYSQL學習筆記02MySQL的高階應用之Explain(完美詳細版,看這一篇就夠了)

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/wx1528159409 最近學習MySQL的高階應用Explain,寫一篇學習心得與總結,目錄腦圖如下: 一、Explain基本概念 1. Explain定義 · 我們知道M

MYSQL學習筆記01MySQL的資料索引Index

最近學習MySQL的索引,以下是一點學習心得與總結: 我們都知道,在java的語法中,index指陣列中的下標;但在MySQL中,index的意思是索引。 1. 何為索引 MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取資料的資料結構。 解構這句話,分析和總結

Django2+ 學習筆記 02win10下Django及新專案部署

1. 安裝Python的Django,貌似是Django命令環境,並不是是專案。(使用--user是因為python安裝到了win的個人使用者下) pip install --user Django==2.1.3 如果本教程時間久遠,你可以用命令pip install --user Dj

Django2+ 學習筆記 01 Django2+官方中文教程

- Django2+需要python3.5+ - 本人做PHP,學習Python爬蟲做點副業。 凡是能作為後端的語言都能寫爬蟲,不要比較哪個語言更牛逼,做就完了。 - 學習目標: 0. 主要學習資料庫驅動的精髓,不管哪種後端語言全部面向api; 1. 比較與Lar

機器學習筆記35蟻群演算法

【參考資料】 【1】《蟻群演算法原理及其應用》 【2】測試資料: https://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz 演算法原理(以TSP問題為例) (1)引數初始化。令時間t=0和迴圈次數

Django2x 學習筆記 03建立path路由url(建立新路由URL,pathinfo模式多個傳參,GET模式多個傳參,返回json)

注意:Django2.1.3 下環境,Python3.7,基於最新的語言和框架的特性。 #1 已新建一個Django專案工程——mysite(假設:F = /django/mysite/ 目錄) django-admin startproject mysite #2&nbs

Django2x 學習筆記 05面向api(模板使用者請跳過),操作已有資料庫的查詢、增加、修改

根據部落格https://blog.csdn.net/itas109/article/details/80898943 才知道如何查詢已有資料庫欄位。 Django官方文件https://docs.djangoproject.com/zh-hans/2.0/寫的真爛,愣是沒找到如何

Linux學習筆記11移動檔案,目錄的mv命令以及關於檢視檔案的技巧

首先給大家分享一下移動檔案、目錄的命令—mv命令(move) (這裡不會像前面那麼詳細地說,因為與前一篇的cp命令有很多相同點,重頭戲在檢視檔案的技巧) mv命令:用於移動檔案或者目錄 mv /tmp/CJlinux/1/2/1.txt /t

Python學習筆記2turtle庫繪相簿使用

5.in[‘C’,’c’]保留字,二元關係操作,符合右側即為真, 6.print(“這裡輸入文字:%.2fF”%f)表示二位小數的浮點數,%f表示輸出的是f的值。 7.迴圈 for i in range (10):                      執行 8.

Python學習筆記3變數型別:數字+字串+元組+列表

11.函式庫引用math,random,turtle。 需要:                  import 庫名 庫名.函式名(變數值) 或者需要:           from庫名import函式名,或者是:from庫名import* 函式名(變數值) 12.

機器學習筆記02最小二乘法(多元線性迴歸模型)

數學基礎 1.轉置矩陣 定義: 將矩陣A同序數的行換成列成為轉置矩陣ATA^TAT,舉例: A=(1203−11)A=\begin{pmatrix} 1 &amp; 2 &amp; 0 \\ 3 &amp; -1 &amp;

機器學習筆記01最小二乘法(一元線性迴歸模型)

【參考資料】 【1】《概率論與數理統計》 【2】 http://scikit-learn.org /stable/auto_examples/ linear_model/ plot_ols.html # sphx-glr-auto-examples-