9
votes

Django Modèle Sous-classing: Obtenez la sous-classe en interrogeant la superclasse

Le code suivant est donné:

class Generic(models.Model):
    basemedium = models.ForeignKey('BaseMedium')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('content_type', 'object_id')


0 commentaires

4 Réponses :


2
votes

Le seul moyen de le faire est de stocker explicitement sur le modèle de base quel type il est. Donc, avez un champ dérived_type (ou autre) sur le fondéumédium, et définissez-le sur Enregistrer. Ensuite, vous pouvez avoir un get_derived_type méthode: xxx

et ainsi de suite.


0 commentaires

2
votes

MERCI M. MR. Roseman pour votre réponse. J'ai développé votre idée un peu plus loin. Voici ce que j'ai proposé:

def related_object(self, default_pointer_name='_ptr'):
        models = [A,B] #models
        object = None

        argument = '%s%s' %(self.__class__.__name__.lower(), default_pointer_name)
        query = { argument : self}

        for model in models:
            try:
                object = model.objects.get(**query)
            except model.DoesNotExist:
                pass
            else:
                return object

        if object == None:
            raise RelatedObjectException
        return object


2 commentaires

Vous devriez faire attention à celui-ci. Si vous avez 1000 enregistrements à extraire de dB, cela se fera dans une sélection, mais il sera ensuite 1000 Sélectionne unique pour obtenir le sous-type pour chaque objet de basemedium. Quoi qu'il en soit, je ne sais pas mieux idée comment faire ça. J'utilise quelque chose de simillar, qui produit beaucoup de requêtes de DB supplémentaires ...


Tirez comme vous avez raison. SQL personnalisé pourrait être une option ... La chose étrange est que je ne comprends pas comment ce n'est pas un problème commun avec la solution connue.



6
votes

Vous devriez vérifier la solution Publié par Carl Meyer il y a quelque temps. Il utilise en interne l'approche de contenu de contenu, mais cela l'encapsule très élégamment.

Il pointe également une solution alternative et plus efficace, qui n'a pas besoin de stocker un champ d'addition sur la base de données, mais il ne fonctionnera que pour les classes d'enfants directes. Si vous avez plusieurs niveaux d'héritage, la première solution est meilleure.


0 commentaires

1
votes

Ceci a fonctionné pour moi (en utilisant Self.subclass_name_in_lower_case): Dans cet exemple, les sous-classes sont TexttreeeItem, CatégorieTetitem et KeyWordTreeitem CODE>.

class TreeItem(MPTTModel):
    parent = TreeForeignKey('self', on_delete=models.CASCADE, verbose_name=_('Parent'),
                            null=True, blank=True, related_name='%(class)s_related')

    objects = CustomTreeManager()

    @property
    def daughter(self):
        try:
            return self.texttreeitem
        except TreeItem.texttreeitem.RelatedObjectDoesNotExist:
            pass

        try:
            return self.categorytreeitem
        except TreeItem.categorytreeitem.RelatedObjectDoesNotExist:
            pass

        try:
            return self.keywordtreeitem
        except TreeItem.keywordtreeitem.RelatedObjectDoesNotExist:
            return self


0 commentaires