Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Modèles réutilisables - modèles abstraits

+5 votes

Je travaille sur un bout d’application (une app au sens django) qui doit être réutilisable par plusieurs projets, seulement ces projets n’ont pas tous les même impératifs et le même mode de fonctionnement.
Une contrainte supplémentaire est que ces projets doivent partager le contenu de cette app à travers une API (Django Rest Framework).

Projet 1 -- App django partagée -- Projet 2
     ------ Contenu ( API DRF ) ---->

Du coup j’ai plusieurs problèmes : je dois étendre les modèles de l’app dans certains projets du coup je dois utiliser soit un héritage multi-table (concrete inheritance) ou bien utiliser un modèle abstrait. Je suis parti sur l’héritage multi-table, mais ça posent plusieurs problèmes : Join à ralonge dans toute les requêtes SQL, complexité en plus de maintenir deux modèles, deux entrées dans l’admin, je dois utiliser des mécanismes pour créer les modèles enfants quand j’importe les modèles parents (comme dit plus haut les projets partagent du contenu à travers une API).

L’interêt d’utiliser la concrete inheritance est que ça me simplifie les processus de synchronisation à travers l’API, j’ai écrit mes fonctions d’import / d’export (serializers) une bonne fois pour toute, elles restent synchro avec mon modèle, chaque projet où j’installe l’app peut directement utiliser l’API pour récupérer du contenu.

Je ne peux pas utiliser directement DRF avec des modèles abstraits du coup ça me compliquerait la tache de les utiliser, il faudrait écrire des serializers pour chaqu’un.

Une troisième option est de ne pas partager d’app entre les projets et de faire en sorte que chaqu’un communique à travers l’API dans un format standard. Ça fait plus de travail et probablement pas mal de répétition de code entre chaque projet…

Je pose cette question pour avoir un point du vue, sur ce que vous feriez dans ce cas là, comment vous gérer des modèles réutilisables et qui en plus communiquent entre plusieurs projets ?

Un peu de code :

class Person(models.Model):
    # Person est le model que je veux partager sur plusieurs projets
    # c’est pour celui-ci que sont écrit les serializers (http://www.django-rest-framework.org/api-guide/serializers/#modelserializer)
    first_name = models.CharField()
    last_name = models.CharField()


class MyCustomPerson(Person):
    # Dans un autre projet je veux utiliser Person, mais en rajoutant quelques attributs
    # En utilisant l’heritage multitable, j’ai plein de JOIN en plus et je dois maintenir la synchro entre Person et MyCustomPerson lorsque je récupère le contenu de Person depuis l’API, mais je n’ai pas besoin de réécrire les serializers.
    score = models.Integerfield()
demandé 30-Jul-2015 par lluuxx (192 points)
edité 30-Jul-2015 par lluuxx

J'ai vraiment du mal à comprendre ce que tu veux dire par "réutilisable" dans ton contexte, est-ce que tu peux nous préciser ça avec un exemple concret, code à l'appui si possible ?

@Debnet +1

Ya rien de plus clair que le code (même si ce n'est qu'un algo)

Ok je rajoute ça

Dans ton exemple, qu'est ce qui t'empêche réellement de passer "Person" en abstrait ?

Dans tous les cas, que ça soit abstrait ou concret, il faudra une API pour chaque sous-type de "Person" car les serializers ne vont pas exposer les mêmes données.

Il n'est pas possible de faire un serializer qui fait le travail inverse cependant, c'est à dire récupérer les données déclinées depuis le modèle concret de base, notamment à cause de l'inconstance des données (incompatible avec le principe REST).

Peux-tu préciser tes contraintes exactes dans ton exemple ?

Ce qui m’empeche de passer «Person» en abstrait c’est de perdre du coup toute la partie API avec DRF, qui ne peut pas utiliser des modèles abstraits ( https://github.com/tomchristie/django-rest-framework/issues/2630#issuecomment-79054997 ).

Pour ce qui est d’utiliser les même serializers je vois bien qu’il n’y a pas les même données, mais j’aimerais pouvoir utiliser le même au moins sur le plus grand ensemble commun de données (Person) quitte a forcer des valeurs par défaut pour le reste.

Dans le cas où par exemple je n’ai que

Projet 1 ------------------- Projet 2
Person     ----  API --- >  MyCustomPerson

Après peut être que la réponse est bien de passer Person en abstract et d’écrire les serializers pour chaque sous classes.

1 Réponse

+4 votes

Personnellement je ne ferais pas de mycustome person, mais plutôt une table séparée genre "personneInfos" qui a une relation "onetoone" avec la table personne. Après, si tu vois que tu as des problèmes de perfs, ce sera une autre question à poser. Mais pour le moment, attend d'avoir des problèmes de perfs évidentes dont tu peux nous apporter les mesures chiffrées avant de chercher à optimiser. Les joins sont certes à limiter, mais les bdd relationelles sont beaucoup plus rapides qu'on ne le lit partout.

répondu 2-Aou-2015 par Sam (4,974 points)

Surtout que la jointure c'est vraiment une opération hyper classique dans les SGBD modernes, PostgreSQL peut en absorber des milliers sur une seule requête sans sourciller.

...