Что такое внутренняя функция в django для разумного добавления новых таблиц в набор запросов? - PullRequest
2 голосов
/ 25 августа 2010

В Джанго 1.2:

У меня есть набор запросов с дополнительным параметром, который ссылается на таблицу, которая в данный момент не включена в запрос, сгенерированный django для этого набора запросов.

Если я добавлю order_by к набору запросов, который ссылается на другую таблицу, django добавит соединения к другой таблице надлежащим образом, и дополнительные работы. Но без order_by дополнительный параметр не работает. Я мог бы просто добавить бесполезный вторичный order_by к чему-то в другой таблице, но я думаю, что должен быть лучший способ сделать это.

Что такое функция django для разумного добавления соединений? Я знаю, что это должно быть где-то вызвано.

Вот пример кода. Он выбирает все показания для данного пользователя и аннотирует результаты оценкой (если таковая имеется) другого пользователя, хранящейся в «друге».

class Book(models.Model):
    name = models.CharField(max_length=200)
    urlname = models.CharField(max_length=200)
    entrydate=models.DateTimeField(auto_now_add=True)

class Reading(models.Model):
    book=models.ForeignKey(Book,related_name='readings')
    user=models.ForeignKey(User)
    rating=models.IntegerField()
    entrydate=models.DateTimeField(auto_now_add=True)

readings=Reading.objects.filter(user=user).order_by('entrydate')

friendrating='(select rating from proj_reading where user_id=%d and \
book_id=proj_book.id and rating in (1,2,3,4,5,6))'%friend.id

readings=readings.extra(select={'friendrating':friendrating})

на данный момент показания не будут работать, потому что соединение с показаниями настроено неправильно. однако, если я добавлю заказ, например:

.order_by('entrydate','reading__entrydate')

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

дополнительная информация:

print readings.query ==>

select ((select rating from proj_reading where user_id=2 and book_id=proj_book.id and  rating in (1,2,3,4,5,6)) as 'hisrating', proj_reading.id, proj_reading.user_id, proj_reading.rating, proj_reading.entrydate from proj_reading where proj_reading.user_id=1;

при условии, user.id = 1 friend.id = 2

ошибка:

OperationalError: Unknown column proj_book.id in 'where clause'

и это происходит потому, что таблица proj_book не включена в запрос. Чтобы повторить то, что я сказал выше - если я сейчас делаю readings2 = readings.order_by ('book__entrydate'), я вижу, что установлено правильное соединение и запрос работает.

В идеале я хотел бы просто выяснить, как называется функция qs.query, которая просматривает две таблицы и выясняет, как они соединяются внешними ключами, и просто вызывать это вручную.

Ответы [ 2 ]

1 голос
/ 27 августа 2010

Ваш сгенерированный запрос:

выберите ((выберите оценку из proj_reading, где user_id = 2 и book_id = proj_book .id и рейтинг в (1,2,3,4,5,6)) as 'hisrating', proj_reading.id, proj_reading.user_id, proj_reading.rating, proj_reading.entrydate из proj_reading, где proj_reading.user_id = 1;

  1. БД не имеет возможностипонять, что это значит под proj_book, так как он не включен в (из таблиц или внутреннего объединения).

  2. Вы получаете ожидаемые результаты, когда добавляете order_by, потому что этот запрос order_byдобавление внутреннего соединения между proj_book и proj_reading.

Насколько я понимаю, если вы ссылаетесь на любой другой столбец в Book, а не только на order_by, вы получите аналогичные результаты.

  • Q1 = Reading.objects.filter (пользователь = пользователь). exclude (Book__name = '') # Исключить силы для добавления JOIN
  • Q2 = "Выбрать рейтинг из proj_reading гдеuser_id =% d "% user.id
  • Result = Q1.extra (" foo ": Q2)

Таким образом, на шаге Q1 вы заставляете DJango добавить объединение в таблицу Book, что не является значением по умолчанию, если только вы не обращаетесь к какому-либо полю таблицы Book.

0 голосов
/ 25 августа 2010

Вы имеете в виду:

class SomeModel(models.Model)
    id = models.IntegerField()
    ...


class SomeOtherModel(models.Model)
    otherfield = models.ForeignKey(SomeModel)

qrst = SomeOtherModel.objects.filter(otherfield__id=1)

Вы можете использовать «__» для создания объединений таблиц.

РЕДАКТИРОВАТЬ: Это не будет работать, потому что вы не определяете объединение таблиц правильно.

myrating='(select rating from proj_reading inner join proj_book on (proj_book.id=proj_reading_id) where proj_reading.user_id=%d and rating in (1,2,3,4,5,6))'%user.id)'

Это pesdocode, и он не тестируется.

Но я советую вам использовать фильтры django вместо написания запросов sql.

read = Reading.objects.filter(book__urlname__icontains="smith", user_id=user.id, rating__in=(1,2,3,4,5,6)).values('rating')

Документация для более подробной информации.

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