每個Geek對折騰自己的博客都有着一份執念
背景介紹
曾經多次在不同的平台寫博客,但全部都以失敗而告終。去年七月選擇微信公眾號做為平台開始了又一次的技術分享,慶幸一直堅持到現在,但隨着文章發表的越來越多,發現公眾號對於PC端很不友好,文章列表沒有PC端入口,查看分享很不方便,所以就利用github pages搭建了一個【運維咖啡吧】的網站,分類展示公眾號內發表的所有文章以及一些未在公眾號發表的瑣碎內容
為了追求極速的瀏覽體驗,整個網站采用純靜態的方式構建,這里的靜態並不是像Jekyll或者Hexo之類的靜態博客框架,而是手寫HTML,頁面少的時候還能應對,但隨着頁面越來越多,維護這些內容就成了災難,好在對Django比較熟悉,於是便動手寫了這么一個靜態博客頁面生成工具
主要功能
網站非常簡單,只有三類頁面,主頁、文章列表頁和文章詳情頁
- 主頁用來分類展示公眾號內的文章列表
- 文章列表頁用來展示網站內文章(一些瑣碎的未在公眾號發表的文章)的列表
- 文章詳情頁用來展示具體文章的內容
基於以上的內容分析,其實只需要做兩個后台頁面,包含幾個小功能,畫個思維導圖
首頁為什么要去讀取JSON文件呢?主要是因為運維咖啡吧的小程序也同時依賴這個JSON文件,修改一個地方避免維護多份數據
最終實現的效果如下圖
接下來介紹下實現這些功能用到的技術或組件
所用技術
讀取及寫入文件
from django.conf import settings
class FileRun:
def __init__(self):
self.file = settings.BASE_DIR + '/ops_coffee/backends/blog.json'
def read(self):
try:
with open(self.file, 'r', encoding='utf8') as f:
return True, f.read()
except Exception as e:
return False, str(e)
def write(self, content):
try:
with open(self.file, 'w', encoding='utf8') as f:
return True, f.write(content)
except Exception as e:
return False, str(e)
讀取及寫入文件的操作與Django的View沒有太大的關系,所以這里我用了一個單獨的類來處理,解釋下其中的四個用法
-
本地文件路徑不要硬編碼到代碼中,盡量采用
settings.BASE_DIR
相對路徑,或者直接將路徑以變量的形式寫入到settings文件,例如我們后邊要說的生成本地文件的目錄就直接在settings中添加了一個變量OPS_COFFEE_GIT_DIR
-
每個方法返回兩個參數狀態和數據
return True,data
,這樣在調用這個方法的時候就可以很方便的判斷出來這個方法是執行成功還是失敗,例如如下代碼
state, data = FileRun().read()
if state:
return(data)
-
讀取文件使用
with
方法可以在你讀取結束后自動執行f.close()
關閉文件,避免因打開文件過多造成的資源消耗 -
使用try來避免程序直接拋錯,有錯誤處理機制
JSON格式化
為了展示好看且能實現語法錯誤提示,采用了jsoneditor
插件,這是一個前端的插件,使用非常簡單
<div class="col-sm-12" id="jsoneditor" style="height:620px"></div>
<script src="/static/js/jsoneditor.min.js"></script>
<script>
// create the editor
var container = document.getElementById("jsoneditor");
var editor = new JSONEditor(container, {
mode: 'code'
});
// set json
editor.set({{ data|safe }});
</script>
JSON Editor 可以用來查看、編輯、格式化和驗證JSON,支持多種模式,例如tree、code、text,當為tree模式時顯示樹狀結構,當為text時顯示純文本,我們這里采用了code模式有行號和顏色,看起來更美觀
safe django從view向template傳遞HTML數據的時候,為了防止html中包含惡意攻擊的代碼django默認不會渲染HTML,所以需要在template接收到html數據后添加|safe
進行渲染
生成HTML
觀察會發現整個網站里所有的頁面除了中間的內容區域之外,其他的地方都一樣,所以我們只需要考慮替換中間的內容就可以了,實際上為了SEO等我們還需要替換title等數據
替換內容生成html文件這里使用了jinja2,我有嘗試直接用django的template來渲染,但最終有一些編碼問題沒有解決,還是采用了jinja2,代碼如下
from jinja2 import Template
from django.conf import settings
tmpl = """<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta name="theme-color" content="#2879d0" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="/css/style.min.css" media="screen" type="text/css" />
<title>{{ title }}</title>
<meta property="og:title" content="{{ title }}" />
<meta property="og:description" content="{{ description }}" />
</head>
<body>
<header>
<div class="inner">
<a href="https://ops-coffee.cn/">
<h1>運維咖啡吧</h1>
</a>
<h2>追求技術的道路上,我從不曾停下腳步</h2>
</div>
</header>
<div id="content-wrapper">
<div class="inner clearfix">
<section id="main-content">
{% if havet %}
<h1 id="art-title">{{ title }}</h1>
{% endif %}
{{ content }}
</section>
<aside id="sidebar">
<blockquote class="route">微信公眾號</blockquote>
<img border="0" src="/images/z-qrcode.jpg" width="100%" height="100%" alt="ops-coffee" />
<blockquote class="route">歸檔列表</blockquote>
<div class="sidebar-list"><a href="/"> 精選文章列表</a></div>
<div class="sidebar-list"><a href="/s/"> 日常運維記錄</a></div>
</aside>
</div>
</div>
</body>
</html>
"""
kwargs = {
"havet": 0,
"title": "運維咖啡吧",
"description": "追求技術的道路上,我從不曾停下腳步",
"content": content
}
_content = Template(tmpl).render(kwargs)
with open(self.blogDir + '/index.html', 'w', encoding='utf8') as f:
f.write(_content)
tmpl 定義了一個模版,模版內可以使用諸如{{ title }}
這樣的變量或是{% if havet %}
這樣的語法
kwargs 定義了一個字典,字典的內容用來替換模版中的變量,字典的key值與模版里邊的變量做匹配,匹配到了就用字典的value填充模版
_content 就是最終html的內容,Template(tmpl).render(kwargs)
會將kwargs的每個key值與模版中的變量做替換
最后會將html內容寫入到html文件
上傳GitHub
網站使用github pages搭建,最后需要將生成的html文件上傳到github,這里我們使用了gitpython
庫,gitpython庫的用法跟原生git的命令非常像,只是命令中間以.
連接
最佳的自動上傳步驟應該是:
- 本地生成ssh密鑰,並將公鑰上傳至github,實現本機與ssh之間的無密碼上傳下載
- 本地創建網站目錄,這個目錄需要跟settings里邊的
OPS_COFFEE_GIT_DIR
變量一致,方便直接將html文件生成在這個目錄下 - 進入網站目錄並使用
git clone
拉取github上的代碼,注意這里應選擇ssh協議的url,例如:git clone git@github.com:ops-coffee/demo.git .
,且確定無需輸入賬號密碼即可拉取 - 然后就可以使用以下程序實現自動上傳更新到github了,也就是在跑本文所講的這個生成工具之前需要先做好以上三步
from git import Repo
from django.conf import settings
class GitRun:
def __init__(self):
self.repo = Repo(settings.OPS_COFFEE_GIT_DIR)
def push(self):
try:
self.repo.git.add(A=True)
self.repo.index.commit('ops-coffee')
self.repo.remote(name='origin').push()
return True, True
except Exception as e:
return False, str(e)
Repo() 選擇已有的git倉庫
git.add 添加本地修改到暫存區,A=True
添加到暫存區時包含刪除文件的修改
index.commit 提交修改到本地倉庫,我這里比較粗糙,統一使用ops-coffee
做為log
repo.remote().push() 選擇遠程分支並提交,name參數表示遠程分支的名字
登陸登出
雖然是個簡單的個人系統,但最基本的用戶認證還是要有的,沒有用Django默認的admin頁面,但還想使用django提供的auth系統實現登陸登出的話,可以采用下邊這種方式
from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [
path('login', LoginView.as_view(template_name='login.html'), name='login-url'),
path('logout', LogoutView.as_view(template_name='login.html'), name='logout-url'),
]
從django.contrib.auth.views
下導入LoginView
和LogoutView
,然后寫兩條url並指定自己的模版位置就可以使用django的登陸登出功能了,這在一些需要簡單認證的系統中非常方便
寫在最后
不斷折騰的過程才是成長最快的過程,用技術來解決實際的問題是對技術最好的應用
如果你對本篇文章的完整源碼感興趣,可以在微信公眾號后台回復“05”獲取,當然也非常歡迎加我個人微信一起學習交流
相關文章推薦閱讀: