2010-07-20 3 views
2

Короче говоря, имена таблиц всех запросов, которые находятся внутри фильтра, переименовываются в u0, u1. .., поэтому мои дополнительные, где предложения не будут знать, на какой таблице указывать. Мне бы очень хотелось, чтобы мне не приходилось вручную делать все запросы для каждого способа, который я мог бы подзадачу по этим данным, и моим текущим обходным путем является превращение моего дополнительного 'd запросов в pk values_lists, но они очень медленные и что-то вроде мерзости.django .extra (where = clauses clobbered by table-renaming .filter (foo__in = ... subselects

Вот как это все выглядит. В основном вы можете игнорировать детали того, что идет в дополнение к этому методу менеджера, за исключением первого sql линия, которая указывает на products_product.id:

def by_status(self, *statii): 
    return self.extra(where=["""products_product.id IN                                     
     (SELECT recent.product_id                                           
      FROM (                                               
      SELECT product_id, MAX(start_date) AS latest                                     
      FROM products_productstatus                                          
      GROUP BY product_id                                            
     ) AS recent                                              
      JOIN products_productstatus AS ps ON ps.product_id = recent.product_id                               
      WHERE ps.start_date = recent.latest                                        
      AND ps.status IN (%s))""" % (', '.join([str(stat) for stat in statii]),)]) 

Это прекрасно работает для всех ситуаций, в которых используется только таблица products_product.

Когда я хочу, чтобы эти продукты как подвыборки, я делаю:

Piece.objects.filter(
    product__in=Product.objects.filter(
     pk__in=list(
      Product.objects.by_status(FEATURED).values_list('id', flat=True)))) 

Как я могу держать обобщенные возможности набора запросов, но по-прежнему использовать дополнительный пункт, где?

+0

Если это не было очевидно, я хочу увидеть «Product.objects.filter (pk__in = list (« часть этого решения уходит ». – outofculture

+0

Не могли бы вы разместить фактический код, который хотите использовать в своем приложении, и запрос, который будет сгенерирован django (даже если он имеет неправильное имя таблицы SQL). Вы можете сделать это с помощью 'print Piece.objects.filter (...). query'. Спасибо! –

+0

Piece.objects.filter (product__in = Product.objects.by_status (FEATURED)) – outofculture

ответ

3

Сперва: проблема не полностью ясна для меня. Является ли второй код в вашем вопросе фактическим кодом, который вы хотите выполнить? Если это так, запрос должен работать так, как ожидалось, поскольку никакого подзапроса не выполняется.

Я предполагаю, что вы хотите использовать второй блок кода без list() вокруг подзапроса, чтобы предотвратить выполнение второго запроса.


документация Джанго относится к этому вопросу in the documentation about the extra method. Однако его нелегко преодолеть.

Самое простое, но наиболее «хакированное» решение - наблюдать, какой псевдоним таблицы создается django для таблицы, которую вы хотите запросить в дополнительном методе. Вы можете полагаться на постоянное именование этого псевдонима, пока вы строите запрос всегда одинаково (вы не меняете порядок нескольких методов extra или filter, вызывающих соединение).

Вы можете проверить запрос, который будет выполнять в QuerySet БД с помощью:

print Model.objects.filter(...).query 

Это выявит псевдонимы, которые используются для таблиц, которые вы хотите запросить.

+0

Правильно, я знаю, что могу переписать дополнительную информацию, где использовать u0, а иногда и u1, в зависимости от ситуации, но мне бы хотелось, чтобы мои шаблоны/представления ребята регулярно устанавливали запрос, который работает так же, как и те, которые я даю им везде. – outofculture