J'essaie d'implémenter un triplestore simple en utilisant l'ORM de Django. J'aimerais être en mesure de rechercher des modèles de triplés arbitrairement complexes (par exemple, comme vous le feriez avec SparQL).
Pour ce faire, j'essaie d'utiliser la fonction .extra() méthode. Cependant, même si la documentation mentionne qu'elle peut, en théorie, gérer les références doubles à la même table en créant automatiquement un alias pour les références de table doubles, j'ai constaté qu'elle ne le fait pas en pratique.
Par exemple, disons que j'ai le modèle suivant dans mon application "triple" :
class Triple(models.Model):
subject = models.CharField(max_length=100)
predicate = models.CharField(max_length=100)
object = models.CharField(max_length=100)
et j'ai les triples suivants stockés dans ma base de données :
subject predicate object
bob has-a hat .
bob knows sue .
sue has-a house .
bob knows tom .
Maintenant, disons que je veux demander les noms de toutes les personnes que Bob connaît qui ont une maison. En SQL, je ferais simplement :
SELECT t2.subject AS name
FROM triple_triple t1
INNER JOIN triple_triple t2 ON
t1.subject = 'bob'
AND t1.predicate = 'knows'
AND t1.object = t2.subject
AND t2.predicate = 'has-a'
AND t2.object = 'house'
Je ne suis pas tout à fait sûr de ce à quoi cela ressemblerait avec l'ORM de Django, même si je pense que ce serait dans le genre :
q = Triple.objects.filter(subject='bob', predicate='knows')
q = q.extra(tables=['triple_triple'], where=["triple_triple.object=t1.subject AND t1.predicate = 'has-a' AND t1.object = 'house'"])
q.values('t1.subject')
Malheureusement, cette opération échoue avec l'erreur "DatabaseError : no such column : t1.subject".
L'exécution de print q.query montre :
SELECT "triple_triple"."subject" FROM "triple_triple" WHERE ("triple_triple"."subject" = 'bob' AND "triple_triple"."predicate" = 'knows'
AND triple_triple.object = t1.subject AND t1.predicate = 'has-a' AND t1.object = 'house')
ce qui semble montrer que le paramètre tables de mon appel à .extra() est ignoré, car il n'y a pas de deuxième référence à triple_triple insérée nulle part.
Pourquoi cela se produit-il ? Quelle est la manière appropriée de faire référence à des relations complexes entre des enregistrements d'une même table en utilisant l'ORM de Django ?
EDIT : J'ai trouvé ceci extrait utile pour inclure du SQL personnalisé via .extra() afin qu'il soit utilisable dans un gestionnaire de modèles.