2010-04-12 2 views
3

J'ai modèle avec une clé étrangère se présente comme suit:Django requête pour sélectionner des parents avec des enfants non nuls

class Concept(models.Model): 
    name = models.CharField(max_length=200) 
    category = models.ForeignKey('self') 

Mais je ne peux pas comprendre comment je peux sélectionner tous les concepts qui ont une valeur pour les enfants non nulle. Est-ce possible avec l'API QuerySet de django ou je dois écrire du SQL personnalisé?

Répondre

3

Si je comprends bien, chaque Concept peut avoir une autre Concept en tant que parent, et ce paramètre est réglé dans le champ category.
En d'autres termes, un Concept avec au moins un enfant sera référencé au moins une fois dans le champ category.

D'une manière générale, ce n'est pas vraiment facile à obtenir dans Django; si vous n'avez pas trop de catégories, vous pouvez penser à une requête de l'analogue de SELECT * FROM CONCEPTS WHERE CONCEPTS.ID IN (SELECT CATEGORY FROM CONCEPTS); - et c'est quelque chose que vous pouvez mapper facilement avec Django:

Concept.objects.filter(pk__in=Concept.objects.all().values('category')) 

Notez que, comme indiqué sur Django documentation, cette requête peut avoir des problèmes de performance sur certaines bases de données; Par conséquent, vous devriez plutôt mettre comme une liste:

Concept.objects.filter(id__in=list(Concept.objects.all().values('category'))) 

Mais s'il vous plaît soyez conscient que cela pourrait frapper une certaine limitation de la base de données - par exemple, Oracle permet jusqu'à 1000 éléments dans ces listes.

+0

Merci pour une explication approfondie! – dragoon

2

Que diriez-vous quelque chose comme ceci:

concepts = Concept.objects.exclude(category=None) 
+0

mais la catégorie n'est pas None pour les concepts sans enfants, votre requête donnera des concepts non catégorisés (concept et catégorie sont essentiellement les mêmes entités) – dragoon

2

La façon dont vous l'avez écrit, il y aura besoin d'une valeur pour category. Une fois que vous avez fixe (avec null=True dans le constructeur de champ), utilisez ceci:

Concept.objects.filter(category__isnull=False) 
Questions connexes