Front Python

在Django中使用LESS

上次振宇介绍duoshuo的开发,前台用的是backbone和LESS,backbone很久之前mentor就提到过,当时没弄懂,等下周休息的时候抽空学学,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又多了很多简单的写法,不会那么无聊,只能一段一段的复制粘贴了。

0 0 投票数
文章评分
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

2 评论
最新
最旧 最多投票
内联反馈
查看所有评论
花似人不同
12 年 前

哈哈哈~因为有用嘛。反正你从你那学来的,就现学现卖喽XD

沈振宇
12 年 前

这么快就自己试了,速度真快啊。