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')
4 Réponses :
Le seul moyen de le faire est de stocker explicitement sur le modèle de base quel type il est. Donc, avez un champ et ainsi de suite. P> p> dérived_type code> (ou autre) sur le fondéumédium, et définissez-le sur Enregistrer. Ensuite, vous pouvez avoir un get_derived_type code> méthode:
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
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.
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. P>
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. P>
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