2016年6月30日 星期四

Node.js筆記:Blog system(1)

練習利用Node.js實作一個Blog:

主要可以分成下列幾項下去實作.
1. 使用Express Web Framework建置一個網站
2. 使用cookie-based session建立會員機制
3. 新增Jade模板動態產生各個頁面
4. 新建自行設計的Restful API處理自訂路由
5. 使用mongoose控制MongoDB資料庫

  1. 使用Express Web Framework建置一個網站
    Express 4.0後提供了一個新的工具“express-generator”, 可以讓我們快速建立一個網站專案, 並幫我們初始化一些基礎設定.
    $npm install express
    $sudo npm install -g express-generator

enter image description here

    $express blog-system

執行express指令時, 後方參數為資料夾名稱.

enter image description here

express命令預設會把express和jade套件填入預先產生的package.json檔中, 所以我們能透過npm install指令把模組安裝完畢.

enter image description here

express 跟 Jade安裝好後就能透過Node.js啟動網站.

    $SET DEBUG=blog-system:* & npm start

打開瀏覽器輸入:http://localhost:3000就可以看到網站了.
enter image description here

npm init指令

Express產生的package.json只有基本的資訊, 這時可利用npm init指令更新專案的相關資訊.

enter image description here

當初入完自訂的資訊之後, 最後會把結果印出來(礙於畫面太長我只截取一小段表示), 如果確定資料正確就會存入package.json中.

安裝mongoose套件

在這邊我們要來修改package.json, 把mongoose套件寫到相依模組(dependencies), 這樣才能把文章寫入MongoDB或是從MongoDB中把文章讀取出來.

新增:
cookie-session是為了用來處理會員登入和登出時可以記得當下的status.

"*"表示版本不限!!!

    "cookie-session": "*",
    "mongoose": "*"

enter image description here

接著透過”npm install”來安裝新增的套件.
enter image description here

2016年6月28日 星期二

Node.js筆記:Express

Express Web Framework

官方定義:
Web Applications

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

主要幫忙解決許多node.js http server 所需要的基本服務,讓開發http service 變得更為容易,不需要像之前需要透過層層模組(module)才有辦法開始編寫自己的程式。

使用Express之後, 它包裝了大多數繁複的HTTP低階操作, 使得我們的程式碼更為精簡.

安裝:
要不要-g(global)就看個人需求.

    npm install -g express

enter image description here

Why use Express?

  1. Express helps you respond to request with route support so that you may write responses to specific URLs.
  2. Supports multiple templating engines to simplify generating HTML.

Explanation of Routes

  • A router maps HTTP requests to a callback(針對從 Client 送來的 URL 做相對應的處理)
  • HTTP requests can be sent as GET/POST/PUT/DELETE …
  • URLs describe the location targeted.
  • To a request handler(callback)
    -> app.<HTTP請求類型>(url,handler{});
    app.get('/index', function(req, res){});

request: 連線要求的資訊和方法:
包含了瀏覽器傳來的各種信息,像是query ,body ,headers,都可以通過req對象訪問到。

response: 回應連線的資訊和方法
我們一般不從裡面取信息,而是通過它來定制我們向瀏覽器輸出的信息,比如 header 信息,比如想要向瀏覽器輸出的內容。這裡我們調用了它的 #send 方法,向瀏覽器輸出一個字符串。

app.get 可以帶入兩個參數,第一個是路徑名稱設定,第二個為Call back function),這裡面就如同前一篇介紹的 createServer 方法,裡面包含 request跟response 兩個物件。使用者就可以透過瀏覽器,輸入不同的url 切換到不同的頁面,顯示不同的結果。

Example:

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

app.get('/', function(req, res){
  res.send('This is GET method');
  res.end;
});

app.listen(process.env.PORT || 12345);

Express middleware

Express在處理一個連線要求時, 利用了middleware的設計, 讓開發者隨時可以自訂或擴充處理的流程. 也可以在適當的時機安插執行一些程式.

為了載入middleware要使用.use, 一個基本middleware長的樣子如下:

function logger(req, res, next){
  console.log(new Date(), req.method, req.url);
  next();
}

Middleware 會收到 3 個參數:
1. req 是 Request 物件,存放這此請求的所有資訊
2. res 是 Response 物件,用來回應該請求
3. next 用來控制流程

上面所寫的logger middleware會把每次request的時間, method還有url都列印在終端機上, 然後呼叫next()往下個middleware過去。Express.js的任務, 就是管理你所有middleware chain。

app.use 和 app.get

再來我們寫一個叫作hello的middleware:

function hello(req, res, next){
  res.write('Hello! \n');
  next();
}

將這個middleware加到我們的middlware chain中:

app.use(logger);
app.get('/hello', hello);
`app.use`表示 所有的request都會執行這個middleware
`app.get`表示 只有針對該URL 做 GET request的時候才會執行這個middleware

Reference:
1. http://expressjs.com
2. https://www.youtube.com/watch?v=czmulJ9NBP0
3. https://dca.gitbooks.io/nodejs-tw-wiki-book/content/book/node_express/node_express.html
4. https://stormpath.com/blog/how-to-write-middleware-for-express-apps
5. http://www.jollen.org/blog/2013/11/expressjs-middleware.html

2016年6月25日 星期六

Node.js筆記:Basic HTTP server

一個基本的網站伺服器流程:
1. 建立HTTP伺服器, 監聽指定的PORT
2. 等待連線
3. 取得新的客戶端連線要求
4. 回傳字串

Example:

var http = require('http');

var server = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World!\n');
});

server.listen(12345);

console.log('Server rinning at http:127.0.0.1:88888/');

enter image description here

上述主要是透過Node內建的http模組, 然後使用http.createServer()去建立伺服器. 最後使用listen()方法去監聽指定的port.

當在cmd中執行上述的程式, 就可以在瀏覽器上輸入127.0.0.1:88888, 就能得到hellow world的回傳結果.

Port

Port:通過端口來區分出同一電腦內不同應用或者進程,從而實現一條物理網線(通過分組交換技術-比如internet)同時鏈接多個程序

端口號是一個16位的uint, 所以其範圍為1 to 65535 (對TCP來說, port 0 被保留,不能被使用. 對於UDP來說, source端的端口號是可選的, 為0時表示無端口).

server.listen(12345),程式在執行時,電腦接收到的12345端口的網路消息就會被發送給我們啟動的這個程式.

2016年6月23日 星期四

Django筆記:自定義過濾器

在這邊只需要記住一點“過濾器本身是一個函數”.

接著要新增一個filter來判斷食物辣或是不辣.

<tr>
    <td> {{ food.name }} </td>
    <td> {{ food.price }} </td>
    <td> {{ food.is_spicy|yes_no:"辣/不辣" }} </td>
    <td> {{ food.comment }} </td>
</tr>

1. 寫一個Filter函式

首先打開myfilters.py

def yes_no(bool_value, show_str):
    if bool_value:
        return show_str.partition('/')[0]
    else:
        return show_str.partition('/')[2]

這邊的函式名稱不需要跟我們定義的過濾器名稱一樣. 但是一樣的話通常會比較好管理.
bool_value是過濾器的第一個參數,他負責接收模板中pipe符號(|)左邊的值;而show_str是第二個參數,會用來接收過濾器中的額外參數, 在這邊指的是”辣/不辣”

2. 註冊該函式

from django import template
...
register = template.Library()
register.filter('yes_no', yes_no)

在這邊我們使用register的filter函式來幫我們註冊, filter函式第一個變數是”過濾器名稱“, 第二個參數是他對應的過濾器函式

3. 載入過濾器

最後就是在模板中載入他

{% load myfilters %}
...

2016年6月22日 星期三

Django筆記:模板繼承

當我們網站模板太多, 而且每一個模板之間共同的部分又很多的時候. 為了一個Don’t repeat yourself的精神. 就可以利用模板繼承的方式把“相似度”高的頁面共同使用同一個模板,方便我們之後的開發.

一個繼承的模板區塊以{% block BLOCKNAME %}為開頭, 以{% endblock %}為結尾. 可以填入內容也可以空白. 接著使用{% extends%}來繼承模板.

原則

  1. 基礎模板中的block越多越好, 並不是要每個區塊都要求繼承. 但是預留更多可變的位置, 會使得模板設計上更靈活
  2. 如果有大量重複的代碼存在各個模板中, 可以考慮抽取出來做成基礎模板.

模板繼承的步驟

  1. 定義基礎模板, 利用{% block BLOCKNAME %}{% endblock %}.
  2. 利用 {% extends%}來繼承模板
  3. 利用模板區塊來覆寫”基礎模板“的內容, 未被覆寫的將用原本模板就設定好的內容.

Example:

#base.html

<!doctype html>
<html>
    <head>
        <title> {% block title %} {% endblock %} </title> 
    </head>
    <body>
        <nav>
            {% if request.user.is_authenticated %}
                <li><a href="#">Hi! {{ request.user }}</a></li>
                <li><a href="/restaurants_list/">餐廳列表</a></li>
                <li><a href="/accounts/logout/">登出</a></li>
            {% else %}
                <li><a href="/accounts/login/">登入</a></li>
                <li><a href="/accounts/register/">註冊</a></li>
             {% endif %}
        </nav>
        <h2>{% block h2 %}{% endblock %}</h2>
        {% block content %}{% endblock %}
    </body>
</html>
#index.html
{% extends "base.html" %}

{% block title %} 首頁 {% endblock %}

{% block content %}
    <h2>歡迎來到Dinbendon</h2>
{% endblock %}