Включение дублирующихся таблиц с использованием Django ORM Extra () - PullRequest
8 голосов
/ 29 июля 2011

Я пытаюсь реализовать простой триплет с использованием ORM Джанго.Я хотел бы иметь возможность искать произвольно сложные тройные паттерны (например, как вы бы сделали с SparQL).

Для этого я пытаюсь использовать метод .extra () .Однако, хотя в документах упоминается, что теоретически он может обрабатывать дубликаты ссылок на одну и ту же таблицу путем автоматического создания псевдонима для ссылок на дубликаты таблиц, я обнаружил, что на практике этого не происходит.

ДляНапример, скажем, у меня есть следующая модель в моем «тройном» приложении:

class Triple(models.Model):
    subject = models.CharField(max_length=100)
    predicate = models.CharField(max_length=100)
    object = models.CharField(max_length=100)

, и в моей базе данных хранятся следующие тройки:

subject predicate object
bob has-a hat .
bob knows sue .
sue has-a house .
bob knows tom .

Теперь, скажем, я хочузапросите имена всех, кто знает, у кого есть дом.В SQL я бы просто сделал:

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'

Я не совсем уверен, как это будет выглядеть с ORM Джанго, хотя я думаю, что это будет в духе:

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')

К сожалению, эта ошибка завершается ошибкой «DatabaseError: нет такого столбца: t1.subject»

Запуск print q.query показывает:

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')

, что указывает на то, что таблицыparam в моем вызове .extra () игнорируется, так как нет второй ссылки на triple_triple, вставленной где-либо.

Почему это происходит?Как правильно ссылаться на сложные отношения между записями в одной и той же таблице, используя ORM Джанго?

РЕДАКТИРОВАТЬ: я нашел этот полезный фрагмент для включения собственного SQL через .extra (), так что этоможно использовать в менеджере моделей.

Ответы [ 2 ]

13 голосов
/ 29 июля 2011

Я думаю, что вам не хватает параметра выбора (для дополнительного метода)

Кажется, это работает:

qs = Triple.objects.filter(subject="bob", predicate="knows").extra(
          select={'known': "t1.subject"},
          tables=['"triple_triple" AS "t1"'],
          where=['''triple_triple.object=t1.subject 
                    AND t1.predicate="has-a" AND t1.object="'''])

qs.values("known")
0 голосов
/ 19 апреля 2015

У меня была та же проблема, когда Django экранирует (добавляет обратные метки) имена моих таблиц, что означает, что я не могу добавить псевдоним вручную; результирующее предложение FROM выглядит так:

"mytable" AS T100

Но в то же время Django не будет автоматически создавать псевдонимы для вас, если таблица уже упоминалась; вместо этого он игнорирует таблицы и просто добавляет предложения WHERE, как если бы они ссылались на исходные таблицы.

Документация для Django 1.8 предполагает, что .extra () создаст для вас псевдонимы:

https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.extra

Но, похоже, это не относится к моему запросу, возможно, потому что исходная таблица является частью LEFT OUTER JOIN, а не простым предложением FROM x, y, z.

...