2009-12-21 8 views
2

Dites, il y a une page qui a beaucoup de blocs associés. Et chaque bloc nécessite un rendu, une sauvegarde et des données personnalisés.Modèles Django modélisation générique

il est plus simple, du point de vue du code, pour définir les différentes classes (donc, modèles) pour chacun de ces modèles. Simplifié comme suit:

class Page(models.Model): 
    name = models.CharField(max_length=64) 

class Block(models.Model): 
    page = models.ForeignKey(Page) 

    class Meta(): 
     abstract = True 

class BlockType1(Block): 

    other_data = models.CharField(max_length=32) 

    def render(self): 
     """Some "stuff" here """ 
     pass 

class BlockType2(Block): 

    other_data2 = models.CharField(max_length=32) 

    def render(self): 
     """Some "other stuff" here """ 
     pass 

Mais,

  • Même avec ce code, je ne peux pas faire une requête comme page.block_set.all() pour obtenir tous les différents blocs, quel que soit le type de bloc.
  • La raison de ce qui précède est que, chaque modèle définit une table différente; Travailler autour pour l'accomplir en utilisant un modèle de liaison et des clés étrangères génériques, peut résoudre le problème, mais il laisse toujours plusieurs requêtes de tables de base de données par page.

Quelle serait la bonne façon de ce modèle? Les clés étrangères génériques (ou quelque chose d'autre) peuvent-elles être utilisées d'une manière quelconque, pour stocker les données de préférence dans la même table de base de données, tout en réalisant des paradigmes d'héritage.

Mise à jour:

Mon point était Comment puis-je obtenir encore les paradigmes de la POO à travailler. En utilisant une même méthode avec tant de ifs n'est pas ce que je voulais faire. La meilleure solution, me semble-t-il, est de créer une classe python standard séparée (de préférence dans un autre blocks.py), qui définit une sauvegarde qui enregistre les données et leur "type" en instanciant le même modèle. Créez ensuite une balise de modèle et un filtre qui appelle le rendu, la sauvegarde et d'autres méthodes basées sur le type du modèle.

Répondre

4

Ne modélisez pas la page dans la base de données. Les pages sont une chose de présentation.

Première - et avant tout - obtenir les données correctes. "Chaque bloc a besoin d'un rendu, d'une sauvegarde et de données personnalisés." Décomposez ceci: vous avez des données uniques. Ignorer le "bloc" et "rendu" à partir d'une perspective de modèle. Il suffit de définir les données sans tenir compte de la présentation.

Sérieusement. Définissez simplement les données dans le modèle sans tenir compte de la présentation ou du rendu ou quoi que ce soit d'autre. Obtenez le bon modèle de données.

Si vous confondez le modèle et la présentation, vous ne serez jamais rien de bien travailler. Et si vous le faites fonctionner, vous ne pourrez jamais l'étendre ou le réutiliser.

Deuxième - seulement après le modèle de données est droit - vous pouvez tourner à la présentation.

Vos « blocs » peut être fait simplement avec des balises HTML <div> et une feuille de style. Essayez cela en premier. Après tout, le modèle fonctionne et est très simple. Ceci est juste HTML et CSS, séparé du modèle.

Vos « blocs » peuvent nécessiter des balises de modèle personnalisé pour créer plus complexe, HTML conditionnel.Essayez cette seconde. Vos «blocs» peuvent - dans un cas extrême - être si complexes que vous devez écrire une fonction de vue spécialisée pour transformer plusieurs objets en HTML. C'est très, très rare. Vous ne devriez pas faire cela tant que vous n'êtes pas sûr de ne pas pouvoir le faire avec des balises de gabarit.


Modifier.

« requête de différentes sources de données externes »

« des classes simples séparés (pas de modèles) qui ont une méthode de sauvegarde, qui écrivent à la même table de base de données. »

Vous avez trois choses complètement différentes, sans rapport.

  • Modèle. Le modèle persistant Avec la méthode save(). Ceux-ci font très, très peu. Ils ont des attributs et quelques méthodes. Pas de "requête différentes sources de données externes". Pas de "rendu en HTML".

  • Sources de données externes. Ce sont des classes Python ordinaires qui acquièrent des données. Ces objets (1) obtiennent des données externes et (2) créent des objets Modèle. Et rien d'autre. Pas de "persistance". Pas de "rendu en HTML".

  • Présentation. Ce sont des modèles Django ordinaires qui présentent les objets Modèle. Aucune requête externe Pas de persistance

+0

Point à propos du modèle de données de droite, merci. Dans mon cas, pour différents types de blocs, j'ai besoin d'interroger différentes sources de données externes et de les rendre dans un html complètement différent. De plus, cachez les données (au niveau du bloc). Donc, les balises de blocage n'aident pas vraiment. Je pense à des classes simples séparées (pas à des modèles) qui ont une méthode save, qui écrivent dans la même table de base de données. –

1

Je viens de terminer un prototype de système qui a ce problème en tête: une classe de produits de base et environ 200 classes de détail qui varient énormément. Il y a beaucoup de situations où nous faisons des requêtes générales contre le produit, mais nous voulons traiter les détails spécifiques à la sous-classe pendant le rendu. Par exemple. obtenir tous les produits du fournisseur X, mais afficher avec des modèles légèrement différents pour chaque groupe d'une sous-classe spécifique.

j'ai ajouté des champs cachés pour un GenericForeignKey à la classe de base et remplit automatiquement le content_type & object_id de la classe des enfants à sauver() temps. Lorsque nous avons un objet générique Product, nous pouvons dire obj = prod.detail et ensuite travailler directement avec l'objet de la sous-classe. J'ai pris environ 20 lignes de code et ça marche très bien.

La seule chose que nous avons rencontrée lors des tests était que manage.py dumpdata suivi de manage.py loaddata jetait Integrity Errors. Il s'avère que c'est un problème bien connu et un correctif est prévu dans la version 1.2. Nous travaillons autour d'elle en utilisant des commandes mysql pour sauvegarder/recharger l'ensemble de données de test.