構建個人博客網站(基於Python Flask)


 

本文由 Ficow Shen 首發於 Ficow Shen's Blog.

 

文章概覽

  • 前言
  • Sketch
  • HTML, CSS, JavaScript
  • Python & Flask & MySQL & SQLAlchemy
  • Gunicorn & Terminal & Command
  • Domain name
  • Nginx & Certbot

 
 

前言

你是否曾經嘗試過搭建個人博客網站?
Hugo, HexoWordPress 這些耳熟能詳的產品,你是否也曾經試用過?
這些產品可以讓你極速搭建個人博客網站,而且你不需要了解太多技術細節。

 

如果你只是想有一個簡單的博客網站只是希望能夠進行內容創作、發表,那么我建議你使用那些產品停止閱讀這篇文章

如果你想DIY你的博客想更深入地了解一個博客系統想學習一些Web和后端技術,那么我建議你繼續閱讀,然后 自己搭建一個博客網站

 

為何選擇 PythonFlask 進行后端開發?

  • Python 簡單易學
  • 對腳本語言感興趣,通過學習 Python 來熟悉 腳本語言
  • Flask 是一個知名且被廣泛應用的后端開發框架,社區非常活躍
  • Python 和 Flask 都有豐富的第三方庫

當然,除了 Python,你也可以選擇 PHP, Golang 等作為后端開發語言。

在學習開始之前,我向你推薦一個網站:Learn X in Y minutes
正如網站名稱說的那樣,你可以在Y分鍾內學習X。該站可以加快你的學習進程,讓你盡快看到內容的全貌。

 
 

Sketch

Sketch

使用 Sketch,主要是為了設計博客頁面
當然,也可以用 PhotoShop 這種類似的軟件。
然后,你就可以參考別人的個人博客頁面,然后設計自己的博客頁面的版式、配色等等。

也許有人會問,有很多現成的主題可以用,為什么還要自己設計呢?

如果你想學習和應用 Web技術,尤其是 CSS 中的 Selector、Flexbox,那么自己寫就可以讓你的學習效果更好。
如果你不感興趣,可以跳過這一步,直接去用別人造好的輪子即可。

如果你覺得 Sketch 實在太貴,請看這里
Sketch 是個很優秀的產品,請您支持正版~

 
 

HTML, CSS, JavaScript

 

HTML 示例:

 <!DOCTYPE html>
<html>
	<head>
		<title>Page Title</title>
	</head>
	<body>
		<h1>This is a Heading</h1>
		<p>This is a paragraph.</p>
	</body>
</html> 

CSS 示例:

body {
  background-color: lightblue;
}
h1 {
  color: white;
  text-align: center;
}
p {
  font-family: verdana;
  font-size: 20px;
}

JavaScript 示例:

document.getElementById("demo").innerHTML = "Hello JavaScript"; 

 

在開始學習之前,我在知乎了解了 零基礎如何迅速學習前端?
然后,在 菜鳥教程 看完了 HTML, CSS, JavaScript 的基礎內容。

相關的基礎知識必須過一遍,甚至幾遍!
要確保自己知道這些技術包含哪些內容,然后你后面需要用到的時候,就可以很容易地找到它們並把它們用起來。

除此之外,還在 MDN 單獨學習了一些技術點,比如:Flexbox.
以及 阮一峰的網絡日志

看了這些東西之后,就需要實操練習。你可以去找一些博客網站來模仿,通過模仿別人的網站來熟悉前端的布局技術。
其實,要點就是:看基礎知識,然后模仿着寫,鞏固學習效果

掌握了這些知識,你就可以寫出靜態的網頁了。

 
 

Python & Flask & MySQL & SQLAlchemy

 

Python 示例:

# -*- coding: UTF-8 -*-

# 該實例輸出 Hello World!
print('Hello World!')

 

讓靜態網頁“活”起來的關鍵是后端提供的數據支持。
學習 Python & Flask & MySQL 之后,你就可以自己定義后端接口,然后為前端提供數據支持。

學習 Python3,了解 Python 的基礎知識點。

掌握了 Python 基礎知識之后,就可以開始學習 Flask 了。
點開 Documentation,里面會有 Quickstart,也有 Tutorial。這兩個部分,不容錯過!

如果覺得閱讀英文文檔的難度太高,你可以看 Flask Web開發:基於Python的Web應用開發實戰
這本書的資源僅供參考,請您支持正版~

 

另外,Flask Tutorial 中使用的是SQLite,但是我建議你使用更好的關系型數據庫,比如:MySQL 或者 PostgreSQL
如何安裝和使用這些數據庫,你可以參考官方文檔或者去搜索引擎找相關的文章來學習。

 

學完這些內容之后,你基本上就已經學會了:
定義后端接口執行數據庫CRUD操作返回網頁數據給前端單元測試 以及 基本的網絡安全知識

把前端和后端的內容結合在一起,網頁的內容就任由你來定義。

 

如果你覺得書寫 SQL 語句很煩人,那么我推薦你使用知名的ORM【對象關系映射(Object Relational Mapping)】 框架 SQLAlchemy
你可以去官方網站找 Tutorial 來快速入門, 比如:SQLAlchemy tutorial

 

這里有兩個示例可供參考。

使用 SQL 語句的示例:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sqlalchemy import create_engine
from sqlalchemy.sql import text

eng = create_engine("mysql://testuser:test623@localhost/testdb")

with eng.connect() as con:

    con.execute(text('DROP TABLE IF EXISTS Cars'))
    con.execute(text('''CREATE TABLE Cars(Id INTEGER PRIMARY KEY, 
                 Name TEXT, Price INTEGER)'''))

    data = ( { "Id": 1, "Name": "Audi", "Price": 52642 },
             { "Id": 2, "Name": "Mercedes", "Price": 57127 },
             { "Id": 3, "Name": "Skoda", "Price": 9000 },
             { "Id": 4, "Name": "Volvo", "Price": 29000 },
             { "Id": 5, "Name": "Bentley", "Price": 350000 },
             { "Id": 6, "Name": "Citroen", "Price": 21000 },
             { "Id": 7, "Name": "Hummer", "Price": 41400 },
             { "Id": 8, "Name": "Volkswagen", "Price": 21600 }
    )
    
    for line in data:
        con.execute(text("""INSERT INTO Cars(Id, Name, Price) 
            VALUES(:Id, :Name, :Price)"""), **line)

 

使用 SQLAlchemy ORM 的示例:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker

eng = create_engine('sqlite:///:memory:')

Base = declarative_base()
 
class Car(Base):
    __tablename__ = "Cars"
 
    Id = Column(Integer, primary_key=True)
    Name = Column(String)  
    Price = Column(Integer)
        
Base.metadata.bind = eng        
Base.metadata.create_all()        
        
Session = sessionmaker(bind=eng)
ses = Session()    

ses.add_all(
   [Car(Id=1, Name='Audi', Price=52642), 
    Car(Id=2, Name='Mercedes', Price=57127),
    Car(Id=3, Name='Skoda', Price=9000),
    Car(Id=4, Name='Volvo', Price=29000),
    Car(Id=5, Name='Bentley', Price=350000),
    Car(Id=6, Name='Citroen', Price=21000),
    Car(Id=7, Name='Hummer', Price=41400),
    Car(Id=8, Name='Volkswagen', Price=21600)])
ses.commit()

觀察后可以發現,使用了 ORM 可以幫助我們專注於業務邏輯。
不用擔心 SQL 語句是否打錯字,也不用擔心它是否能正常執行並返回預期的結果。

 
 

Gunicorn & Terminal & Command

學習完 Flask 之后,你已經知道了開發服務器和生產服務器的區別。
為了更好的性能以及安全性,在部署博客系統的時候,你需要使用一個生產服務器。

我選擇了 Gunicorn,配置比較簡單(入門容易),而且用戶群也比較龐大(遇到問題更容易解決)。
參考 Gunicorn 的教程,你可以很容易地完成相關的配置。

 

Gunicorn 配置示例:

import multiprocessing

bind = '127.0.0.1:8000'
workers = multiprocessing.cpu_count() * 2 + 1

backlog = 2048
worker_class = "gevent"
worker_connections = 1000
daemon = False
debug = True
proc_name = 'gunicorn_demo'
pidfile = './log/gunicorn.pid'
errorlog = './log/gunicorn.log'

 
使用 Gunicorn 之后,你可以很容易地配置后端應用的訪問地址、進程數、日志路徑、運行模式等等。

 

在你打算部署服務器時,你會發現你必須使用 命令行工具

首先,啟動 Gunicorn 需要執行命令行指令,比如:gunicorn --paste development.ini -b :8080 --chdir /path/to/project
然后,連接遠程服務器需要使用 SSH, 比如: ssh root@127.0.0.1

推薦你學習 Linux 教程Shell 教程 。在部署后台系統到遠程服務器的過程中,你會反復用到如 cd, ls, vim 等這些命令。所以,學習這些命令是必需的步驟。

 

如果你還沒有購買雲服務器,那我推薦你使用 Vultr 的服務器。
優點:便宜、不用備案、輕松部署強力愛國上網等等
缺點:延遲高、經常有黑客來訪等等

當然,你也可以購買知名的 AWS、阿里雲、騰訊雲、UCloud 等等廠商的雲服務器。

 
 

Domain name

擁有自己的博客的同時,你是不是也希望能夠擁有一個特別的網站域名,比如自己的名字?

現在以 http://ficow.cn 為例來講解域名相關的知識。

你可以訪問 http://www.ficow.cn,也可以訪問 http://ficow.cn
但是,如果我訪問 http://123.ficow.cn 就無法看到正常的頁面。為什么呢?
因為我在域名解析頁面進行了相應的配置,http://ficow.cnhttp://www.ficow.cn 都是我希望別人可以正常訪問的網頁。

 

阿里雲 域名注冊首頁

我是在 阿里雲(原萬網) 購買了 ficow.cn 這個域名,當然你也可以選擇其他的域名提供商購買域名。

 

在購買了域名之后,就可以登錄控制台進行域名解析

控制台 域名解析

在主機記錄這一列,我配置了 wwwblog。這兩個均指向了同一個IP,也就意味着目前我是依靠這一台服務器來處理個人首頁博客
關於域名配置的詳細內容,你可以參考域名提供商提供的幫助文檔,也可以直接通過搜索引擎尋找答案,這里就不贅述了。

但是,你是不是比較好奇,兩個不同的主機記錄竟然指向了同一台服務器。服務器是如何對不同的主機記錄進行解析的呢? 接下來,Nginx 會告訴你答案~

 
 

Nginx & Certbot

Nginx 是一個高性能反向代理服務器,它可以將遠程服務器上收到的數據轉發給你的后台程序。用它來處理靜態文件請求非常方便。

這是一個 Nginx server 的配置 Demo:

server
{
        access_log /home/xxx/path/to/project custom_log;
        server_name blog.ficow.cn;

        charset utf-8;
        root /home/xxx/path/to/project;

        # Proxy connections to the application servers
        location / {
            proxy_pass         http://0.0.0.0:5000;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            client_max_body_size 10M;
        }
}

你可以通過簡單地配置 Nginx 來監聽 80 端口,然后讓它根據域名來區分以及轉發數據給你的后台程序。
在上面的示例中,Nginx 會把指向 blog.ficow.cn 的訪問請求轉發給 http://0.0.0.0:5000, 限制客戶端請求中body最大為 10M。

當然,你可以讓多個 server_name 都使用這同一套配置。你還可以定義多個 server,然后對不同的 server_name 進行不同的定制化處理,比如:負載均衡

想了解更多關於如何配置 Nginx 的內容,請參考官網文檔。

如果你希望你的博客網站支持 HTTPS,我推薦你使用 Certbot
Certbot 的最大優勢就是:免費、易用,這對於一個個人博客系統來說,簡直完美~

 

在 Ubuntu 系統上安裝 Certbot 的示例:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx 

自動配置 Nginx 的 SSL 相關參數:

certbot --nginx

編輯定時任務,定期調起 Certbot 去更新 SSL 證書:

crontab -e

插入本行內容,並保存退出,定時任務即可生效

# 分  時  某月中的幾號  幾月  星期幾  *代表任何時候 ,分隔多個相同類型的參數
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew

如果系統默認打開的編輯器不是vim,可以修改環境變量
在~/.profile中加入以下內容,並保存退出

vim ~/.profile
export EDITOR="/usr/bin/vim";

加載更新的EDITOR配置:

source ~/.profile

然后再重新使用crontab -e添加定時更新 SSL 證書的任務即可。

然后,嘗試使用HTTPS來訪問你的博客吧!


免責聲明!

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



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