Использование select_related и дополнительного предложения - PullRequest
1 голос
/ 19 июля 2010

Я пытаюсь добиться некоторого дополнительного выбора в наборе запросов и хочу добавить нужную таблицу в пул таблиц в запросе, используя метод select_related, чтобы воспользоваться синтаксисом __.

Вот пример с простыми моделями:

from django.db import models

# Create your models here.

class testA(models.Model):
    code = models.TextField(unique = True)
    date = models.DateTimeField(auto_now_add = True)

class testB(models.Model):
    text = models.TextField()
    a = models.ForeignKey(testA)

А вот запрос, который я хочу построить:

SELECT (extract(hour from testa.date)) AS hour, testb.text FROM testb INNER JOIN testa ON (testb.a_id = testa.id)

Итак, вот как я собираю его в python:

testB.objects.all().select_related('a').extra(select = {'hour' : 'extract(hour from testa.date)'}).values('hour','text')

но django удаляет select_related, когда видит, что я не использую таблицу "testa" (из-за выражения 'values').Таким образом, полученный SQL-запрос завершается ошибкой:

SELECT (extract(hour from testa.date)) AS "hour", "testb"."text" FROM "testb"

Если я удаляю оператор «values», он работает нормально:

SELECT (extract(hour from testa.date)) AS "hour", "testb"."id", "testb"."text", "testb"."a_id", "testa"."id", "testa"."code", "testa"."date" FROM "testb" INNER JOIN "testa" ON ("testb"."a_id" = "testa"."id")

, но я должен поставить оператор values, как я хочу, чтобы составлять агрегатыкак в «подсчете объектов b, сгруппированных по часу даты в объекте a»:

testB.objects.all().select_related('a').extra(select = {'hour' : 'extract(hour from testa.date)'}).values('hour').annotate(count = Count('pk'))

Итак, каков хороший способ добиться этого?«Подсчитать объекты, сгруппированные по чему-то в другом объекте»?Или есть способ «заставить» django сохранить таблицы «select_related», даже если он считает, что они бесполезны?

PS: я знаю, что мог бы использовать аргумент «tables» дополнительного оператора, но в этомВ этом случае мне придется самостоятельно переписать объединение, и я хочу воспользоваться django ORM

Ответы [ 3 ]

1 голос
/ 20 июля 2010

Я разработал приложение Django для решения таких проблем: django-cube . Основная идея состоит в том, чтобы эмулировать многомерную БД, чтобы легко вычислять агрегации.

Требуемая вами функциональность ('__hour': поиск по полю для 'hour') не реализована, но ее реализация займет, вероятно, 15 минут. Так что читайте, что дальше, как это работает и т. Д. ... и если это соответствует вашим потребностям, напишите мне, и я выполню это.

Примеры на главной странице и в api doc не актуальны (они будут через несколько дней), но это фрагменты . Если вы хотите попробовать, вот как вы можете решить эту проблему с django-cube:

#install the app first ...
from cube.models import Dimension, Cube

class MyCube(Cube):
    #declare a dimension called 'hour_a',
    #that is related to the field 'a__date__hour'.
    hour_a = Dimension(field='a__date__hour')

    #declare how to calculate the aggregation on a queryset
    @staticmethod
    def aggregation(queryset):
        return queryset.count()

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

cube(testB.objects.all()).measure_dict('hour_a', full=False)

Что бы вернуть что-то вроде:

{   
    12: {measure: 889},
    13: {measure: 6654},
    14: {measure: 77},
    #<hour>: <count>
}

Кроме того, не берите рекомендованную загрузку, а извлекайте ее из источника (ветка 0.3).

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

0 голосов
/ 20 июля 2010

Я получаю ту же ошибку локально: все работает, пока не добавляются «значения», а затем django не может разместить соответствующее предложение FROM. Я хотел бы опубликовать этот пример в группе django-users и посмотреть, сможет ли кто-нибудь из знающих проверить, является ли это ошибкой или есть быстрое исправление.

0 голосов
/ 20 июля 2010

Я не могу ответить на ваш основной запрос, но стоит отметить, что select_related не имеет ничего общего с синтаксисом __.select_related - это просто оптимизация, которая будет возвращать дополнительные связанные объекты, добавляя соединения в запрос при необходимости.Но синтаксис с двойным подчеркиванием для запросов к связанным таблицам работает с select_related или без него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...