Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

Publicaciones sobre python (publicaciones antiguas, página 73)

Nikola 1.2 en la calle!

Por­qué ha­cer si­tios es­tá­ti­co­s? Por­que no usan re­cur­so­s, por­que son a prue­ba de fu­tu­ro, por­que es fá­ci­l, son se­gu­ro­s, y por­que no te ata a una pla­ta­for­ma.

Fea­tu­res nue­vo­s:

  • Ga­­le­­rias de imá­­ge­­nes (po­­­nés fo­­­tos en una ca­r­­pe­­ta y lis­­to)

  • Se­r­­ver web in­­co­r­­po­­­ra­­do pa­­ra pre­­views ("­­doit -a se­r­­ve")

  • Co­­­man­­dos pa­­ra crear nue­­vos po­s­­ts fá­­ci­l­­men­­te ("­­doit -a new_­­po­s­­t")

  • So­­­po­r­­te de Google Si­te­­maps

  • Un ma­­nua­­l!

  • Si­­tio de de­­mo co­m­­ple­­ti­­to in­­cluí­­do

  • So­­­po­r­­ta de­­plo­­­y­­ment au­­to­­­má­­ti­­co ("­­doit -a de­­plo­­­y")

  • Re­­di­­re­c­­cio­­­nes clien­­t-­­si­­de

Y por su­pues­to los fea­tu­res vie­jo­s:

  • Es­­cri­­bís los po­s­­ts en res­­tru­c­­tu­­red text

  • Es­­ti­­lo li­m­­pio y cus­­to­­­mi­­za­­ble (con boots­­tra­­p)

  • Co­­­men­­ta­­rios via Dis­­qus

  • So­­­po­r­­ta cua­l­­quier sis­­te­­ma de ana­­li­­ti­­cas web

  • Blogs con tags, fee­­d­s, fee­­ds pa­­ra tags, pá­­gi­­nas de ín­­di­­ce, ín­­di­­ce por año, por ta­­g, y má­s.

  • Fun­­cio­­­na co­­­mo CMS pa­­ra co­­sas que no son pa­r­­te del blog

  • Te­m­­pla­­tes li­m­­pios y cus­­to­­­mi­­za­­bles (u­san­­do Mako)

  • Pu­­ro py­­thon y po­­­co py­­thon (u­­nas 600 lí­­nea­s)

  • Bui­l­­ds in­­te­­li­­gen­­tes (só­­­lo ge­­ne­­ra las pá­­gi­­nas ne­­ce­s­a­­ria­s, gra­­cias a doi­­t)

  • Fá­­cil de agre­­gar nue­­vos co­­­man­­dos y op­­cio­­­nes

  • Mues­­tra có­­­di­­go con re­s­al­­ta­­do de si­n­­ta­­xis

En es­te mo­men­to Niko­la ha­ce to­do lo que yo ne­ce­si­to, así que si al­guien lo prue­ba y ne­ce­si­ta al­go­... bue­no, es un buen mo­men­to pa­ra pe­dir :-)

Más in­fo en http://­niko­la-­ge­ne­ra­to­r.­google­co­de.­com

¡Nikola 1.1 en la calle!

Lo es­cri­bí pa­ra es­te mis­mo si­tio, pe­ro de­ci­dí que tal vez sea útil pa­ra otro­s. Los ob­je­ti­vos prin­ci­pa­les de Niko­la so­n:

  • Po­­­co có­­­di­­go: po­r­­que no quie­­ro man­­te­­ner un mon­s­­truo pa­­ra es­­te blo­­­g.

  • Ge­­ne­­ra­­ción rá­­pi­­da de pá­­gi­­na­s: aña­­dir un post no de­­be­­­ría ta­r­­dar mas de 5 se­­gun­­dos en re­­contruir el si­­tio.

  • Ge­­ne­­rar si­­tios es­­tá­­ti­­co­­s: de­­plo­­­y­­ment usan­­do rs­­yn­­c!

  • Ge­­ne­­ra­­ción fle­­xi­­ble de pá­­gi­­na­s: po­­­dés de­­ci­­dir ado­n­­de te­r­­mi­­na ca­­da co­­­sa en el si­­tio.

  • Te­m­­pla­­tes po­­­de­­ro­­sas: Usa Mako

  • Ma­­rkup li­m­­pio pa­­ra los po­s­­ts: Usa Do­­­cu­­tils

  • No ha­­ce bui­l­­ds idio­­­ta­s: Usa doit

  • HT­­ML li­m­­pio por de­­fau­l­­t: Usa boots­­trap

  • Co­­­men­­ta­­rios sin lío­­s: Usa Dis­­qus

  • Tags, con sus pro­­­pios fee­­ds

  • Fá­­cil pa­­ra ha­­cer blogs

  • Pá­­gi­­nas fue­­ra del blog

  • Si­­tios mu­l­­ti­­li­n­­gües

Creo que es­ta ver­sión ini­cial lo­gra esos ob­je­ti­vo­s, pe­ro por su­pues­to es me­jo­ra­ble. Se agra­de­ce el fee­dba­ck!

La pá­gi­na de Niko­la es http://­niko­la-­ge­ne­ra­to­r.­google­co­de.­com

¡Unicode en Python es Divertido!

>>> 'á'.decode('utf8')
u'\xe1'

Sin em­bar­go, hay una tram­pa. Te­nés que es­tar ab­so­lu­ta­men­te se­gu­ro que la co­sa que es­tás de­co­dean­do es un string de by­tes, y no un ob­je­to uni­co­de. Por­que los ob­je­tos uni­co­de tie­nen un mé­to­do de­co­de pe­ro es to­tal­men­te inú­ti­l, y su úni­co pro­pó­si­to en la vi­da es cau­sar es­te error pe­cu­lia­r:

>>> u'á'.decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1'
in position 0: ordinal not in range(128)

¿Por­qué es pe­cu­lia­r? Por­que es un error de En­co­de. Cau­sa­do por lla­mar a de­co­de. Lo que pa­sa es que en los ob­je­tos uni­co­de, de­co­de, en la prác­ti­ca es al­go así:

def decode(self, encoding):
    return self.encode('ascii').decode(encoding)

El usua­rio quie­re un ob­je­to uni­co­de. Él tie­ne un ob­je­to uni­cde. Por de­fi­ni­ció­n, no exis­te un co­sa que sea "de­co­dear co­mo utf-8 un ob­je­to uni­co­de". No tie­ne sen­ti­do. Es co­mo pei­nar un pes­ca­do, o es­ca­lar una la­gu­na.

¡Lo que debería devolver es self! Además es suamente molesto que la única manera de evitar el error es chequear el tipo del objeto, lo que es activamente antipitónico.

Aún me­jo­r, no ten­ga­mos un mé­to­do de­co­de en ob­je­tos uni­co­de, que creo es la si­tua­ción en py­thon 3, pe­ro nun­ca lo va a ser en py­thon 2.

Así que aho­ra ya sa­be­n, y bue­na suer­te.

Nikola está Cerca

  • Im­­ple­­men­­té tags (i­n­­clu­­yen­­do fee­­ds pa­­ra ca­­da ta­­g).

  • Si­m­­pli­­fi­­qué los te­m­­pla­­tes.

  • Se­­pa­­ré có­­­di­­go y co­n­­fi­­gu­­ra­­ció­­n.

El úl­ti­mo fué el más com­pli­ca­do. Y pa­ra que se vea co­mo es, és­ta es la con­fi­gu­ra­ción com­ple­ta, ex­cep­to pe­da­ci­tos de HT­ML que no va­len la pe­na ve­r, co­mo el có­di­go de google cus­tom sear­ch. ¡Es­pe­ro que sea cla­ro!

# -*- coding: utf-8 -*-

# post_pages contains (wildcard, destination, template) tuples.
#
# The wildcard is used to generate a list of reSt source files (whatever/thing.txt)
# That fragment must have an associated metadata file (whatever/thing.meta),
# and opcionally translated files (example for spanish, with code "es"):
#     whatever/thing.txt.es and whatever/thing.meta.es
#
# From those files, a set of HTML fragment files will be generated:
# whatever/thing.html (and maybe whatever/thing.html.es)
#
# These files are combinated with the template to produce rendered
# pages, which will be placed at
# output / TRANSLATIONS[lang] / destination / pagename.html
#
# where "pagename" is specified in the metadata file.
#

post_pages = (
    ("posts/*.txt", "weblog/posts", "post.tmpl"),
    ("stories/*.txt", "stories", "post.tmpl"),
)

# What is the default language?

DEFAULT_LANG = "en"

# What languages do you have?
# If a specific post is not translated to a language, then the version
# in the default language will be shown instead.
# The format is {"translationcode" : "path/to/translation" }
# the path will be used as a prefix for the generated pages location

TRANSLATIONS = {
    "en": "",
    "es": "tr/es",
    }

# Data about this site
BLOG_TITLE = "Lateral Opinion"
BLOG_URL = "//ralsina.me"
BLOG_EMAIL = "ralsina@kde.org"
BLOG_DESCRIPTION = "I write free software. I have an opinion on almost "\
    "everything. I write quickly. A weblog was inevitable."

# Paths for different autogenerated bits. These are combined with the translation
# paths.

# Final locations are:
# output / TRANSLATION[lang] / TAG_PATH / index.html (list of tags)
# output / TRANSLATION[lang] / TAG_PATH / tag.html (list of posts for a tag)
# output / TRANSLATION[lang] / TAG_PATH / tag.xml (RSS feed for a tag)
TAG_PATH = "categories"
# Final location is output / TRANSLATION[lang] / INDEX_PATH / index-*.html
INDEX_PATH = "weblog"
# Final locations for the archives are:
# output / TRANSLATION[lang] / ARCHIVE_PATH / archive.html
# output / TRANSLATION[lang] / ARCHIVE_PATH / YEAR / index.html
ARCHIVE_PATH = "weblog"
# Final locations are:
# output / TRANSLATION[lang] / RSS_PATH / rss.xml
RSS_PATH = "weblog"

# A HTML fragment describing the license, for the sidebar.
LICENSE = """
    <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/ar/">
    <img alt="Creative Commons License" style="border-width:0; margin-bottom:12px;"
    src="http://i.creativecommons.org/l/by-nc-sa/2.5/ar/88x31.png"></a>
"""

# A search form to search this site, for the sidebar. Has to be a <li>
# for the default template (base.tmpl).
SEARCH_FORM = """
    <!-- google custom search -->
    <!-- End of google custom search -->
"""

# Google analytics or whatever else you use. Added to the bottom of <body>
# in the default template (base.tmpl).
ANALYTICS = """
        <!-- Start of StatCounter Code -->
        <!-- End of StatCounter Code -->
        <!-- Start of Google Analytics -->
        <!-- End of Google Analytics -->
"""

# Put in global_context things you want available on all your templates.
# It can be anything, data, functions, modules, etc.
GLOBAL_CONTEXT = {
    'analytics': ANALYTICS,
    'blog_title': BLOG_TITLE,
    'blog_url': BLOG_URL,
    'translations': TRANSLATIONS,
    'license': LICENSE,
    'search_form': SEARCH_FORM,
    # Locale-dependent links
    'archives_link': {
        'es': '<a href="/tr/es/weblog/archive.html">Archivo</a>',
        'en': '<a href="/weblog/archive.html">Archives</a>',
        },
    'tags_link': {
        'es': '<a href="/tr/es/categories/index.html">Tags</a>',
        'en': '<a href="/categories/index.html">Tags</a>',
        },
    }

execfile("nikola/nikola.py")

Bienvenidos a Nikola

Así que, ahí va una ex­pli­ca­ció­n:

  • Ca­m­­bié to­­­do el so­­­ftwa­­re y los te­m­­pla­­tes pa­­ra es­­te blo­­­g.

  • Sí, es­­tá to­­­do sin te­r­­mi­­na­­r.

  • El nue­­vo so­­­ftwa­­re se lla­­ma Niko­­­la.

  • Sí, creo que es­­tá bue­­no.

¿Porqué cambiar?

¿En se­rio? EL ge­ne­ra­dor an­te­rior (Son of Bar­tle­Blo­g) no es­ta­ba en buen es­ta­do. Los ar­chi­vos cu­brían só­lo 2000-2010, el li­nk "pos­ts an­te­rio­res" era una qui­nie­la, y a la ver­sión en es­pa­ñol le fal­ta­ban pá­gi­nas en­te­ra­s.

¿Qué es Nikola?

Niko­la es un ge­ne­ra­dor de si­tios es­tá­ti­co­s. Una co­sa in­te­re­san­te de es­te si­tio es que es, y siem­pre ha sio, pu­ro HT­M­L. Ca­da co­sa "di­ná­mi­ca" que veas acá, co­mo ser co­men­ta­rio­s, es un ser­vi­cio de ter­ce­ro­s. Es­te si­tio es na­da más que unas car­pe­tas lle­nas de HT­M­L.

¿Cómo funciona Nikola?

Niko­la to­ma una car­pe­ta lle­na de ar­chi­vos txt es­cri­tos en res­truc­tu­red text, y ge­ne­ra frag­men­tos de HT­M­L.

Esos frag­men­to­s, con un po­co de me­ta­da­ta (tí­tu­lo, tags, nom­bre del ar­chi­vo de sali­da, li­nks a fuen­tes ex­ter­na­s) y unos Mako Tem­pla­tes crean pá­gi­nas HT­M­L.

Esas pá­gi­nas usan boots­trap pa­ra no ser una re­ve­ren­da ba­zo­fia (nun­ca di­je ser un di­se­ña­do­r).

Pa­ra ase­gu­rar­me de no ha­cer tra­ba­jo inú­ti­l, doit se en­car­ga de re­crear lo mí­ni­mo in­dis­pen­sa­ble.

¿Por qué no usar <esto>?

Por­que, por di­ver­sas ra­zo­nes, que­ría man­te­ner exac­ta­men­te las URLs que siem­pre tu­ve.

  • Si mue­­vo una pá­­gi­­na, man­­te­­ner aso­­­cia­­dos los co­­­men­­ta­­rios de Dis­­qus es un ba­r­­do.

  • Pue­­de ha­­ber gen­­te que te­­ga book­­ma­­rks.

Ade­más quie­ro:

  • Mako te­m­­pla­­tes (po­r­­que me gus­­tan)

  • Res­­tru­c­­tu­­red text (po­r­­que ten­­go más de 1000 po­s­­ts es­­cri­­tos en eso)

  • Py­­thon (pa­­ra ha­­ckea­r­­lo)

  • Fá­­cil de ha­­ckear (Niko­­­la es­­tá por las 600 LO­­­C, y es ca­­si fea­­tu­­re co­m­­ple­­te)

  • So­­­po­r­­te de blogs mu­l­­ti­­li­n­­gües co­­­mo es­­te.

Y por su­pues­to:

  • So­­­na­­ba co­­­mo un pro­­­ye­c­­to co­r­­to y di­­ve­r­­ti­­do. Te­­nía la so­s­­pe­­cha que con un po­­­co de pe­­ga­­men­­to las he­­rra­­mien­­tas exis­­ten­­tes ha­­cían el 90% del tra­­ba­­jo. Pa­­re­­ce que te­­nía ra­­zó­­n, ya que lo pu­­de es­­cri­­bir en unos po­­­cos dia­s.

¿Lo vas a mantener?

Y, lo es­toy usan­do­...

¿Es útil para alguien más?

No por aho­ra, por­que ha­ce mon­to­nes de su­po­si­cio­nes vá­li­das só­lo pa­ra es­te si­tio. hay que lim­piar­lo un po­co an­tes de que que­de lin­do.

¿Lo pueden usar los demás?

Pronti­to, es­pe­ro.

¿Faltan features?

No tie­ne tags, y al­gu­na co­si­ta me­no­r.


Contents © 2000-2023 Roberto Alsina