Accueil » Tutoriels Zope » Adapters Zope 3

Adapters Zope 3

Document Actions

Par gawel le 13/03/2007 22:18

Les adapteurs Zope 3, une introduction à la component architecture.

Catégories : Zope3

Les adapters

Les adapters Zope 3 rajoutent des fonctionnalités à un objet. Exemple, nous avons deux classes:

class Gruik(object):
    attribut21 = u'je suis issue de la classe Gruik'

class Gruik2(object):
    def titre(self):
        return u'je suis issue de la classe Gruik2'

On aimerais pouvoir appeler un attribut 'titre' sur ces deux objets de façon transparente. Pour cela, il nous faut une interface:

import zope.interface

class IGruikTitre(zope.interface.Interface):
    titre = zope.interface.Attribute(u'un titre')

Puis, 2 adapters qui implémentent notre interface et adaptent nos classes:

import zope.component

class GruikTitre(object):
    zope.interface.implements(IGruikTitre)
    zope.component.adapts(Gruik)
    def __init__(self,context):
        self.context = context

    def _titre(self):
        return self.context.attribut21

    titre = property(_titre,None)

class GruikTitre2(object):
    zope.interface.implements(IGruikTitre)
    zope.component.adapts(Gruik2)
    def __init__(self,context):
        self.context = context

    def _titre(self):
        return self.context.titre()

    titre = property(_titre,None)

On enregistre ses deux adapters (normalement via des zcml):

zope.component.provideAdapter(GruikTitre)
zope.component.provideAdapter(GruikTitre2)

On est ensuite capable d'appeler l'attribut titre sur nos deux classes en passant par leur adapter:

>>> gruik = Gruik()
>>> IGruikTitre(gruik).titre
u'je suis issue de la classe Gruik'
>>> gruik2 = Gruik2()
>>> IGruikTitre(gruik2).titre
u'je suis issue de la classe Gruik2'

On appelle donc l'interface sans ce soucier de quel adapter est appelé.

Les multi-adapters

Il est possible de définir des adapters pour plusieurs objets:

class Animal(object):
    description = u'un animal'

class Nourriture(object):
    description = u'de la nourriture'

class IRepas(zope.interface.Interface):
    pass

class Repas(object):
    zope.interface.implements(IRepas)
    zope.component.adapts(Animal,Nourriture)

    def __init__(self,animal,nourriture):
        self.animal = animal
        self.nourriture = nourriture

    def ilmangequoi(self):
        return u'au repas, %s mange %s' % (self.animal.description,
                                           self.nourriture.description)

zope.component.provideAdapter(Repas)

Ce qui nous permet en suite d'adapter l'animal à sa nourriture via le repas:

>>> animal = Animal()
>>> nourriture = Nourriture()
>>> repas = zope.component.queryMultiAdapter((animal,nourriture))
>>> repas.ilmangequoi()
u'au repas, un animal mange de la nourriture'

Les adapters nommés

Il est possible de nommer des adapters. En surclassant notre précédent Repas, nous pouvons en créer de nouveau qui porterons un nom:

class PetitDej(Repas):

    def ilmangequoi(self):
        return u"au petit des, %s mange %s abondamment pour prendre des forces !" % (self.animal.description,
                                                                                  self.nourriture.description)
class Diner(Repas):

    def ilmangequoi(self):
        return u"au diner, %s fais la diète pour ne pas être ballonné la nuit" % self.animal.description

zope.component.provideAdapter(PetitDej,name='ptitdej')
zope.component.provideAdapter(Diner,name='diner')

Puis les utiliser explicitement:

>>> animal = Animal()
>>> nourriture = Nourriture()
>>> repas = zope.component.queryMultiAdapter((animal,nourriture),name='ptitdej')
>>> repas.ilmangequoi()
u'au petit des, un animal mange de la nourriture abondamment pour prendre des forces !'
>>> repas = zope.component.queryMultiAdapter((animal,nourriture),name='diner')
>>> repas.ilmangequoi()
u'au diner, un animal fais la di\xe8te pour ne pas \xeatre ballonn\xe9 la nuit'

Conclusion

Toute l'architecture de Zope 3 est basé sur les interfaces et les adapters (je vous conseil la lecture des README de zope.interface et zope.component). La vue d'un objet est, par exemple, un multi-adapter nommé qui adapte un context et une request et dont le nom est, la plupart du temps, le .html que l'on appelle.

Il est possible, grâce à ce système de redéfinir tout ou partie du comportement de votre application. La façon dont sont générés l'id de vos objets (voir INameChooser) ou la façon dont il sont traversé (voir ITraver)par exemple.

Aidez l'AfPy

Rechercher
Dernières news AFPY
Les 6 dernières news
PyCon FR - 17-18 mai - Paris
07/05/2008 07:05
AFPyro d'Avril
24/04/2008 00:00