使用tornado和angularjs搭建網站


 

從這篇博文開始,將講述建立一個站點的全過程。一方面自己從未做過這類事情,算是對自己的一個挑戰,另一方面也給想要學這個的同胞留點參考,特別是*需要課程設計作業和畢業設計的同志們*。

首先介紹一下網站功能。這次要建立的一個網站類似於一個在線的辯論場,用戶可以發起辯論,自由選擇題目,邀請其他用戶參加。參加辯論的用戶可以自由選擇自己論點,分正反雙方辯論,當然也可以選擇中立進行攪渾水。

關於要用到的技術。后端采用Python開發,框架選用Tornado,前端使用AngularJS配合jQuery,數據庫選擇PostgreSQL,操作系統當然要用Ubuntu了。

這里選擇的技術完全是因為個人喜好,絕不是因為和其他方案相比有啥優劣之分。另外,因為我也使用過Python、JavaScript,但從未做過實際的項目,所以代碼質量可能會比較丟人。

### 關於Tornado ###
Tornado是一個使用Python開發的web框架,按其作者說法,Tornado從另一個小巧的框架web.py借鑒了很多東西。和其他框架不同,Tornado並不是很龐大的一個框架,只是提供了一些基本的功能,帶來的好處是比較靈活,和其他功能模塊可以很容易結合到一塊,缺點則是工作量多點。

##### Tornado在Ubuntu下的安裝 ####
首先安裝pip
sudo apt-get install python-pip
然后安裝Tornado
sudo pip install tornado
當然,也可以使用easy_install來安裝。

#### Tornado入門 ####
先來看一個簡單的Tornado例子(代碼來自tornado官網)
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")

application = tornado.web.Application([
(r"/", MainHandler),
])

if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

用tornado開發web應用還是比較簡單的,主要步驟就是如上所示,設置好(URL, Handler)的映射,至於其他功能,還有待進一步學習。


### 關於AngularJS ###
AngularJS是從大Google出來的前端框架,提供了數據綁定等功能,但是沒有對DOM操作進行封裝,所以和jQuery代培使用比較好。

### 關於PostgreSQL ###
PostgreSQL是一個開源的關系型數據庫,功能強大,但是國內的普及度不高,自從9.2開始原聲支持json之后,再加上本身又提供類似按列存儲的功能,國外有些人已經開始把它當作NoSQL來用了。

 

這系列博文中即將建立的站點稱為“嘚啵嘚”。

## 數據庫表的設計 ##

"嘚啵嘚"使用的數據庫是PostgreSQL,因此你要確定自己的系統中已經安裝好了它。網上關於這方面的文章很多,不再說了。

#### 首先建立開發者賬戶,數據庫 ####

create role developer with password 'developer';
alter role developer LOGIN;

create database debate;
grant all privileges on database debate to developer;

#### 接下來建立三個表,users用於存儲用戶信息,debates用於存儲辯論自身的相關信息,arguments用於存儲用戶的論點(也就是發言內容)。 ####

建立用戶信息表,這里我們只需要存儲用戶的帳號(使用email地址,需要保證唯一)、密碼以及賬戶狀態,同時要對每一個用戶生成一個獨立的ID,並在此ID上建立主鍵約束。

CREATE TABLE users
(
user_id serial NOT NULL, -- 用戶ID
email character(256) NOT NULL, -- 用戶郵箱地址
passwd character(128) NOT NULL, -- 用戶密碼
state smallint NOT NULL DEFAULT 0, -- 賬戶狀態:0--未激活 1--已激活
CONSTRAINT users_pk_id PRIMARY KEY (user_id),
CONSTRAINT user_uk_email UNIQUE (email)
)
WITH (
OIDS=FALSE
);
ALTER TABLE users
OWNER TO developer;
COMMENT ON TABLE users
IS '用戶信息表';
COMMENT ON COLUMN users.user_id IS '用戶ID';
COMMENT ON COLUMN users.email IS '用戶郵箱地址';
COMMENT ON COLUMN users.passwd IS '用戶密碼';
COMMENT ON COLUMN users.state IS '賬戶狀態:0--未激活 1--已激活';

建立辯論表。

CREATE TABLE debates
(
debate_id serial NOT NULL, -- 辯論題目ID
originator serial NOT NULL, -- 發起人ID
create_time date NOT NULL DEFAULT now(), -- 發起時間
supportors_count integer NOT NULL DEFAULT 0, -- 支持者人數
opposers_count integer NOT NULL DEFAULT 0, -- 反對者人數
neutral_count integer NOT NULL DEFAULT 0, -- 中立者人數
topic character(1024) NOT NULL, -- 辯論主題
support_argument character(1024) NOT NULL, -- 正方觀點綜述
oppose_argument character(1024) NOT NULL, -- 反方觀點綜述
CONSTRAINT debate_pk_id PRIMARY KEY (debate_id),
CONSTRAINT debate_fk_originator FOREIGN KEY (originator)
REFERENCES users (user_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE debates
OWNER TO developer;
COMMENT ON COLUMN debates.debate_id IS '辯論題目ID';
COMMENT ON COLUMN debates.originator IS '發起人ID';
COMMENT ON COLUMN debates.create_time IS '發起時間';
COMMENT ON COLUMN debates.supportors_count IS '支持者人數';
COMMENT ON COLUMN debates.opposers_count IS '反對者人數';
COMMENT ON COLUMN debates.neutral_count IS '中立者人數';
COMMENT ON COLUMN debates.topic IS '辯論主題';
COMMENT ON COLUMN debates.support_argument IS '正方觀點綜述';
COMMENT ON COLUMN debates.oppose_argument IS ' 反方觀點綜述';

建立參加者觀點表

CREATE TABLE arguments
(
argument_id serial NOT NULL, -- 論點ID
debater_id serial NOT NULL, -- 辯論者ID
debate_id serial NOT NULL, -- 所屬辯論ID
type integer NOT NULL DEFAULT 2, -- 論點類型:0--反對 1--支持 2--中立
publish_date date NOT NULL DEFAULT now(), -- 發布時間
viewpoint character(1024) NOT NULL, -- 觀點
CONSTRAINT argument_id PRIMARY KEY (argument_id),
CONSTRAINT argument_fk_debate FOREIGN KEY (debate_id)
REFERENCES debates (debate_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT argument_fk_debater FOREIGN KEY (debater_id)
REFERENCES users (user_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE arguments
OWNER TO developer;
COMMENT ON COLUMN arguments.argument_id IS '論點ID';
COMMENT ON COLUMN arguments.debater_id IS '辯論者ID';
COMMENT ON COLUMN arguments.debate_id IS '所屬辯論ID';
COMMENT ON COLUMN arguments.type IS '論點類型:0--反對 1--支持 2--中立';
COMMENT ON COLUMN arguments.publish_date IS '發布時間';
COMMENT ON COLUMN arguments.viewpoint IS '觀點';

其實在實際開發中,表名、數據庫名、索引等最好加上前綴或者后綴來作區分,向上面這樣數據庫叫debates,里邊有個表也叫debates其實是不太好的。

## 下面講一下Python下操作PostgreSQL用到的模塊psycopg2。 ##

### 安裝psycopg2和 ###

安裝過程需要安裝postgresql-server-dev以及python-devel

sudo apt-get install postgresql-server-dev python-devel
sudo pip install psycopg2

##### psycopg2使用實例 #####

import psycopg2
import psycopg2.extensions
import psycopg2.extras

con = psycopg2.connect(host=‘localhost’,
post=5432,
user='developer',
password='developer',
database='debate')

cursor = con.cursor(cursor_factory=psycopg2.extras.DictCursor)

cursor.execute('select * from debates where debate_id = %s;', (debate_id,))

debate = cursor.fetchone();

con.commit()

這個模塊用起來還是比較方便的,值得注意的是cursor.execute中的sql語句結尾的分號不能省略,而且第二個參數必須要是序列(List或者Tuple)

## 站點頁面設計 ##
由於前端使用AngularJS,所以這次打算徹底一點,作成一個單頁應用,所有前端的渲染都使用js繪制。后端除了初始頁面之外,提供的都是數據。

這一個系列博客的代碼都放在了Github上,地址是http://github.com/JimmyChange/debate

#### 代碼主文件的設計 ####

// server.py
import tornado.ioloop
import tornado.web

import handlers

setting = [
]

application = tornado.web.Application([
(r"/", handlers.HomeHandler),
(r"/login", handlers.LoginHandler),
(r"/users/([0-9]+)", handlers.UserHandler),
(r"/debates", handlers.DebatesHandler),
(r"/debates/([0-9]*)", handlers.DebateHandler),
(r"/debates/([0-9]+)/arguments", handlers.ArgumentsHandler),
(r"/debates/([0-9]+)/arguments/([0-9]*)", handlers.ArgumentHandler),
])

if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()


// handlers.py
......

class DebatesHandler(BaseHandler):
def get(self):
self.write("Debates Handler")

class DebateHandler(BaseHandler):
def get(self, debate_id):
self.write(debate_id)
self.write("Debate Handler")

def post(self, debate_id):
self.write(debate_id)
self.write("Debate Handler")

def put(self, debate_id):
self.write(debate_id)
self.write("Debate Handler")

def delete(self, debate_id):
self.write(debate_id)
self.write("Debate Handler")

......

上面只是代碼的一部分,列在這里是為了說明一下URL的格式。對於/collections的操作都是對於整個集合的,而對於/collection/的都是針對單個項目的。

今天就折騰這些,下午打球把他媽腳扭了,得歇着。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM