Wilane' Weblog

jaZZ ... just another Zine Zblog

Billets étiquetés « Zine Python Blog »

Ecrire un greffon Zine par l'exemple

écrit par Ousmane Wilane, le 13/05/09 22:06.

Ce greffon flickr permettra d’afficher les albums (sets) de photos

Pour ce projet on utilisera une api flickr appelée flickrapi redoutable par sa simplicité.

Arborescence du projet

  • flickr/
    • docs/
    • i18n/
    • __init__.py
    • metadata.txt
    • templates/
      • admin/

Notez que dans le répertoire `scripts` du code source vous trouverez un script `new-plugin` permettant de définir l’échafaudage ci-dessus avec les méta données sur l’auteur et le greffon consignées dans `metadata.txt’.

Interface admin

Il faut permettre au Blogeur d’enregistrer son API KEY et le USER_ID pour lequel il va afficher les albums de photo, pour cela on ouvre __init__.py avec emacs (si vous utilisez un autre éditeur arrêter de lire tout de suite):

from os.path import dirname, join

from werkzeug import escape, url_encode

import zine
from zine.api import *
from zine.widgets import Widget
from zine.views.admin import flash, render_admin_response
from zine.privileges import BLOG_ADMIN, require_privilege
from zine.utils.validators import ValidationError, check
from zine.utils.http import redirect_to
from zine.utils import forms

USER_AGENT = 'Zine /%s | Flickr/0.1' % zine.__version__
FLICKR_URL_BASE = 'static.flickr.com'
FLICKR_VERSION = '0.1'
TEMPLATES = join(dirname(__file__), 'templates')

def is_valid_key():
    def validate(form, apikey):
        pass
    return validate

def is_valid_userid():
    def validate(form, userid):
        pass
    return validate

def add_flickr_link(req, navigation_bar):
    if req.user.has_privilege(BLOG_ADMIN):
        for link_id, url, title, children in navigation_bar:
            if link_id == 'options':
                children.insert(-3, ('flickr',
                                     url_for('flickr/config'),
                                     _('Flickr')))

class ConfigurationForm(forms.Form):
    api_key = forms.TextField(validators=[is_valid_key()])
    user_id = forms.TextField(validators=[is_valid_userid()])

@require_privilege(BLOG_ADMIN)
def show_flickr_config(req):
    form = ConfigurationForm(initial=dict(
        api_key=req.app.cfg['flickr/apikey'],
        user_id=req.app.cfg['flickr/userid'],
    ))

    if req.method == 'POST' and form.validate(req.form):
        if form.has_changed:
            req.app.cfg.change_single('flickr/apikey',
                                      form['api_key'])
            req.app.cfg.change_single('flickr/userid',
                                      form['user_id'])
            if form['api_key'] and form['user_id']:
                flash(_('Flickr has been successfully enabled.'), 'ok')
            else:
                flash(_('Flickr disabled.'), 'ok')
        return redirect_to('flickr/config')
    return render_admin_response('admin/flickr.html',
                                 'options.flickr',
                                 form=form.as_widget())


def setup(app, plugin):
    app.add_config_var('flickr/apikey',
                       forms.TextField(default=u''))

    app.add_config_var('flickr/userid',
                       forms.TextField(default=u''))

    app.add_url_rule('/options/flickr', prefix='admin',
                     endpoint='flickr/config',
                     view=show_flickr_config)

    app.connect_event('modify-admin-navigation-bar', add_flickr_link)

Avec ce petit bout de code vous réalisez l’essentiel du travail de configuration du greffon. `add_config_var()’ définit les deux variables de configuration qui seront enregistrées dans le fichier `zine.ini’ dans le répertoire de l’instance, `add_url_rule()’ définit le mapping entre l’url et la vue qui traite l’url et enfin `add_flickr_link()’ est invoquée lorsque la barre de navigation de l’admin est déssinée. Le reste du code se lis simplement.

Template admin/flickr.html

{% extends "admin/layout.html" %}
{% block title %}{{ _("Flickr Configuration") }}{% endblock %}
{% block contents %}
  <h1>{{ _("Flickr Configuration") }}</h1>
  <p>Flickr integration. If you don't have a flickr.com account yet, you can
    get one at <a href="{{ api_link }}">flickr.com</a>.
  </p>

  {%- call form() %}
  <h2>API Key</h2>
    <p>{{ form.api_key() }}</p>
  <h2>User Id</h2>
    <p>{{ form.user_id() }}</p>
    <div class="actions">
      <input type="submit" value="{{ _('Update') }}">
    </div>
  {%- endcall %}
{% endblock %}

Widget flickr du Blog

Avec une API KEY et un USER ID, nous allons définir la fonction permettant de récupérer les albums de chez flickr, ensuite de faire le rendu du widget qui va afficher les vignettes avec un lien vers la page de l’album sur flickr.

def jsonFlickrApi(q):
    return q

def get_sets_urls():
    # FIXME: Error checking please
    import flickrapi
    app = get_application()
    
    api_key=app.cfg['flickr/apikey']
    user_id=app.cfg['flickr/userid']    
    flickr = flickrapi.FlickrAPI(api_key, format='json')
    sets = eval(flickr.photosets_getList(user_id=user_id))
    
    return [{'url':'http://www.flickr.com/photos/wilane/sets/%s' %(i['id'],), 
             'urlimg':'http://farm%s.static.flickr.com/%s/%s_%s_s.jpg' %(i['farm'], i['server'], i['primary'], i['secret'])}  
             for i in sets['photosets']['photoset']]

class FlickrWidget(Widget):
    name = 'get_flickr_sets'
    template = 'flickr_widget.html'

    def __init__(self, show_title=True, title='Flickr sets'):
        self.show_title = show_title
        self.title = title
        self.sets = get_sets_urls() 

    @staticmethod
    def get_display_name():
        return _('Flickr sets')

def setup(app, plugin):
    app.add_widget(FlickrWidget)
    app.add_template_searchpath(TEMPLATES)

Là encore le travail consiste à définir le widget et à lui injecter (`self.sets’) la liste de dictionnaire contenant l’image de l’album (en petite taille s – voire la documentation de l’api sur flickr.com –) et l’url

Template flickr_widget.html

Et enfin voici la template utilisée pour le rendu du widget:

{% extends 'widgets/base.html' %}
{% block title %}{{ widget.title }}{% endblock %}
{% block body %}
 {%- for set in widget.sets %}
  <a href="{{ set.url }}"><img src="{{ set.urlimg }}" /> </a>
 {%- endfor %}
{% endblock %}

Si vous désirez ensuite distribuer votre greffon vous pouvez utiliser le script `bundle-plugin’ dans le répertoire `scripts’ pour produire le `.plugin’ utilisée pour installer votre greffon par l’interface web d’admin d’une instance de Zine