在Django中使用LESS
LESS一種動態樣式語言,簡單來說就是對CSS語言的擴展,可以類比于coffeescript對javascript提煉。我因為 javascript寫習慣了,轉到coffeescript效率不升反降。但用LESS重寫了幾個CSS文件,絕對是快了很多。因為LESS沒有改變 CSS的寫法(唯一變化的是注釋可以用//了),所以沒有轉換障礙。LESS擁有語言的特征,例如變量、函數、命名空間等,和只是樣式表的CSS比起來靈 活了許多。
在前臺使用LESS的方式和coffeescript很像,也是載入一個js文件用來處理less后綴的文件,將其轉換成CSS。
<link rel="stylesheet/less" type="text/css" href="/static/css/styles.less"> <script src="/static/js/less.js" type="text/javascript"></script>
當然如果真這么處理,就和Django沒什么關系了,我一般是在模板里直接用{%block style%}寫CSS樣式,所以如果能自定義一個templatetag,直接在里面寫LESS那是最順手的。
Install
大致的思路是在Django中制作一個模板標簽,調用lessc命令處理其中的語句。所以先裝上nodejs,用nodejs的npm工具安裝less,完成后建立一個軟鏈接以便直接使用lessc命令。
wget http://nodejs.org/dist/v0.6.5/node-v0.6.5.tar.gz tar xzvf node-v0.6.5.tar.gz cd node-v0.6.5/ ./configure make make install npm install less ln -s ~/node-v0.6.5/node_modules/less/bin/lessc /usr/local/bin/lessc
Django Template Tag
思路很簡單,用Python的NamedTemporaryFile和shlex,把自定義tag中的LESS代碼寫入一個臨時文件,用shlex執行lessc來解析,獲得返回的內容輸出到模板就可以了。
from tempfile import NamedTemporaryFile from django import template import subprocess, shlex, os register = template.Library() class LessNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist def lessc(self, source): #創建臨時文件, delete=False這樣close的時候不會刪除 less_file = NamedTemporaryFile(delete=False) less_file.write(source) less_file.close() #用lessc執行創建的臨時文件 cmd = shlex.split("lessc %s" % ( less_file.name)) run = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) #獲得解析完成的css css, error = run.communicate() os.remove(less_file.name) if error: print error else: return css.decode("utf-8") def render(self, context): output = self.nodelist.render(context) return self.lessc(output) def do_less(parser, token): nodelist = parser.parse(("endless",)) parser.delete_first_token() return LessNode(nodelist) register.tag('less', do_less)
除了lessc是執行業務邏輯的代碼以外,其他的都是定義template tag用的固定代碼,所以也就沒必要寫注釋了,詳細解釋可以參考官方文檔。
Usage
把以上代碼存為less.py文件,放到應用下的templatetag目錄中,然后載入它,例如:
{% load i18n less %} {% less %} .corners (@radius: 5px) { border-radius: @radius; -webkit-border-radius: @radius; -moz-border-radius: @radius; } form { #id_username {.corners} #id_password {.corners(10px)} } {% endless %}
實際輸出的CSS:
<style> form #id_username { border-radius: 5px; -webkit-border-radius: 5px; -moz-border-radius: 5px; } form #id_password1 { border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; } </style>
Afterword
寫完以后準備提交到github,發現已經有一個名為django-less的 項目了,不止有template tag,還可以直接解析.less文件,從它的安裝說明推斷,應該也是直接用lessc命令來實現的,所以如果像我一樣只需要tag就沒必要裝了,順便以 同樣的方法寫了coffeescript的tag,沒準以后用得上。如果對靜態文件處理的需求比較復雜,還可以用django-assets來進行處理。LESS還有很多有趣的特性,以后寫CSS又多了很多簡單的寫法,不會那么無聊,只能一段一段的復制粘貼了。