osa1 feed

Django'ya Pygments desteği

August 26, 2010 - Tagged as: python, django, tr.

Daha önceden burada Django’ya Markdown desteği eklenmesinden bahsetmiştim(Django’nun Markdown eklentisi olduğunu farkettim çok sonradan). Bu sefer de syntax renklendirme için Pygments desteği ekledim. Pygments’den önce syntaxhighlighter kullanıyordum benim amacım için biraz fazla gelişmiş ve kompleks kaçıyordu.

Öncelikle django’ya pygments desteği için 2 tane çok iyi kaynak var(1, 2), fakat bu kaynaklardaki yöntemlerden ilki, veritabanına gerekli html tagları eklenmiş bir şekilde yazıyor, dolayısıyla bir daha düzenlemek istediğinizde kodunuz okunmaz bir halde oluyor. Benim yapmak istediğim şey, daha önceden markdown için de yaptığım gibi, bir template filter oluşturup istediğim yerde kullanabilmek. Hem bu şekilde daha esnek olabilirim. İkinci yöntem ise, açıkçası ne yaptığını anlamaya çalışmadım, markdown ve pygments’i beraber uyguluyor. Bu da benim istediğim şey değil. Benim amacım, istediğim yere markdown, istediğim yere pygments, istediğim yere de ikisini beraber uygulamak.

Bunun için verdiğim ilk kaynaktaki kodu kullandım aslında. Tek farkı, sonucu veritabanına yazdırmak yerine, fonksiyonu template filter haline getirdim.

# pygmentsf.py
from django import template
from BeautifulSoup.BeautifulSoup import BeautifulSoup #saka gibi
from pygments import lexers, highlight, formatters
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def pygmentsf(html):
    "String'i Pygments'den gecirir. BeautifulSoup ile pre taglarini ayristirir."
    soup = BeautifulSoup(html)
    preblocks = soup.findAll('pre')
    for pre in preblocks:
        if pre.has_key('class'):
            try:
                code = ''.join([unicode(item) for item in pre.contents])
                code = unescape_html(code)
                preclass = pre['class']
                # syntaxhighlighter icin yazilmis kodlar icin
                if preclass == 'brush: python' or preclass == 'brush; python':
                    preclass = 'python'
                lexer = lexers.get_lexer_by_name(preclass)
                formatter = formatters.HtmlFormatter()
                code_hl = highlight(code, lexer, formatter)
                pre.replaceWith(BeautifulSoup(code_hl))
            except:
                pass
    return unicode(soup)
def unescape_html(html):
    html = html.replace('&lt;', '<')
    html = html.replace('&gt;', '>')
    html = html.replace('&amp;', '&')
    return html

Ayrıca küçük bir düzenlemeyle daha önceden syntaxhighlighter için yazdığım yazılarla da uyumlu olmasını sağladım. Bu dosyayı uygulamanız altında eğer templatetags klasörüne attıktan sonra template dosyanızdan {% load pygmentsf %} dedikten sonra, istediğiniz değişkene uygulayabilirsiniz. {{ blog.body|pygmentsf|safe|escape }} gibi. Ya da isterseniz markdown yazımdaki template filter ile beraber {{ blog.body|markdown|pygmentsf|safe|escape }} şeklinde kullanabilirsiniz.

Unutmadan, HTML’i ayrıştırmak için BeautifulSoup kullanılıyor. Mükemmel bir kütüphane.

Eğer markdown ile beraber kullanacaksanız, bu yöntem pek de iyi değil. Şuraya bakın.