Backend

Le backend pour une version (par exemple Magento 1.7) est représenté par une instance de la classe Backend.

Chaque connecteur va aussi créer un connector.backend qui permet aux utilisateurs d’inscrire leurs backends. Par exemple le connecteur Magento a un magento.backend (_inherit connector.backend_model.connector_backend). Ce modèle contient un champ version qui doit avoir la même lists de versions (avec exactement le même nom) que les instances de Backend.

Exemple avec le connecteur Magento

# in magentoerpconnect/backend.py

magento = backend.Backend('magento')
""" Generic Magento Backend """

magento1700 = backend.Backend(parent=magento, version='1.7')
""" Magento Backend for version 1.7 """

# in magentoerpconnect/magento_model.py

class MagentoBackend(models.Model):
    _name = 'magento.backend'
    _description = 'Magento Backend'
    _inherit = 'connector.backend'

    _backend_type = 'magento'

    @api.model
    def _select_versions(self):
        """ Available versions

        Can be inherited to add custom versions.
        """
        return [('1.7', 'Magento 1.7')]

    # <snip>

    version = fields.Selection(
        selection='_select_versions',
        string='Version',
        required=True,
    )
    location = fields.Char(string='Location', required=True)
    username = fields.Char(string='Username')
    password = fields.Char(string='Password')

    # <snip>

Dans le code ci-dessus, “1.7” est la clé de correspondance entre l’instance de Backend (magento1700) et l’enregistrement magento_backend.

class connector.backend.Backend(service=None, version=None, parent=None, registry=None)[source]

Bases : object

Un backend représente un système avec lequel interagir, comme Magento, Prestashop, Redmine, …

Il possède trois propriétés :

service

Le nom du service, par exemple “magento”

version

La version du service. Par exemple “1.7”

parent

Un backend parent. Lorsqu’aucune classe ConnectorUnit n’est trouvée pour un backend, elle est cherchée dans le parent.

La structure des Backends est la partie clé du framework, mais elle est plutôt simple.

  • Une instance de Backend contient un registre de classes ConnectorUnit
  • Il peut renvoyer la classe ConnectorUnit à utiliser pour une tâche
  • Si aucune ConnectorUnit n’est inscrite pour une tâche, le parent direct est interrogé (et ainsi de suite)

Les Backends ont deux mécanismes différents d’extension. L’un est plus vertical (entre plusieurs versions) et l’autre est plus horizontal car il permet de modifier le comportement pour une version donnée du backend.

Pour l’exemple, disons que nous avons les versions suivantes de backend

         <Magento>
             |
      -----------------
      |               |
<Magento 1.7>   <Magento 2.0>
      |
<Magento with specific>

Et voici la façon dont elles sont déclarées en Python

magento = Backend('magento')
magento1700 = Backend(parent=magento, version='1.7')
magento2000 = Backend(parent=magento, version='2.0')

magento_specific = Backend(parent=magento1700, version='1.7-specific')

Dans le graphe ci-dessus, <Magento> va contenir toutes les classes partagées entre toutes les versions. Chaque version de Magento (<Magento 1.7>, <Magento 2.0>) va utiliser les classes définies sur <Magento>, sauf si elles ont inscrit leur propres classes. C’est la même chose pour <Magento avec specifique> mais celui-ci contient des personnalisations qui sont spécifiques à une instance (typiquement pour mettre en place des mappeurs spécifiques à une instance).

Voici comment inscrire des classes sur <Magento> et une autre sur <Magento 1.7>

@magento
class Synchronizer(ConnectorUnit):
    _model_name = 'res.partner'

@magento
class Mapper(ConnectorUnit):
    _model_name = 'res.partner'

@magento1700
class Synchronizer1700(Synchronizer):
    _model_name = 'res.partner'

Ici, la méthode get_class() appelé sur magento1700 renverrait

magento1700.get_class(Synchronizer, session, 'res.partner')
# => Synchronizer1700
magento1700.get_class(Mapper, session, 'res.partner')
# => Mapper

C’est le mécanisme d’extension verticale, il dit que chaque version fille est capable d’étendre ou remplacer le comportement de son parent.

Note

when using the framework, you won’t need to call get_class(), usually, you will call connector.connector.ConnectorEnvironment.get_connector_unit().

L’extension verticale est celle que vous utiliserez probablement le plus, parce que la plupart des choses que vous modifierez concerne vos applications personnalisées ou des comportements différents selon les versions du backend.

Cependant il peut arriver que nous ayons besoin de changer le comportement d’un connecteur, en installant un module. Par exemple, imaginons que nous ayons déjà un ImportMapper pour les articles dans le Connecteur Magento. Nous créons un module (générique) pour gérer le catalogue d’une manière plus avancée. Nous redéfinissons un AdvancedImportMapper qui devrait être utilisé quand le module est installé. Ceci est le mécanisme d’extension horizontal.

Remplace une clase ConnectorUnit par une autre dans le backend

@backend(replacing=ImportMapper)
class AdvancedImportMapper(ImportMapper):
    _model_name = 'product.product'

Avertissement

L’extension horizontale devrait être utilisée de manière très occasionnelle et précautionneuse, car dès que deux modules voudront remplacer la même classe il y aura un conflit (qui nécessiterait de créer un troisième module pour lier les deux, le remplacement pouvant prendre un tuple de classes à remplacer et ceci étant exponentiel). Ce mécanisme ne devrait être utilisé que dans certains circonstances bien précises pour des modules génériques.

get_class(base_class, session, model_name)[source]

Trouve une sous-classe correspondante à base_class dans les classes inscrites.

Paramètres:
match(service, version)[source]

Utilisé pour trouver le backend pour un service et une version

register_class(cls, replacing=None)[source]

Inscrit une classe dans le backend

Paramètres:
service

Modèles du backend