Как получить связанные объекты при вызове extra().values() в Django?

StackOverflow https://stackoverflow.com/questions/1138360

  •  16-09-2019
  •  | 
  •  

Вопрос

Благодаря этому сообщению я могу легко подсчитывать и группировать запросы в представлении Django:

Эквивалент Django для подсчета и группировки по

В моем приложении я отображаю список типов монет и их номиналов, доступных в моей базе данных для страны, поэтому монеты из Великобритании могут иметь номинальную стоимость «1 фартинг» или «6 пенсов».А face_value это 6, currency_type это «пенс», хранящийся в связанной таблице.

На мой взгляд, у меня есть следующий код, который дает мне 90% пути:

def coins_by_country(request, country_name):
    country = Country.objects.get(name=country_name)
    coin_values = Collectible.objects.filter(country=country.id, type=1).extra(select={'count': 'count(1)'},
                               order_by=['-count']).values('count', 'face_value', 'currency_type')
    coin_values.query.group_by = ['currency_type_id', 'face_value']
    return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )

А currency_type_id выглядит как число, хранящееся в поле внешнего ключа (т.е.4).Я хочу получить фактический объект, на который он ссылается как часть запроса (модель Currency, чтобы я мог получить поле Currency.name в своем шаблоне).

Как лучше всего это сделать?

Это было полезно?

Решение 2

select_related() подошел довольно близко, но он хотел, чтобы я добавил каждое поле, которое я выбрал, в group_by пункт.

Поэтому я попробовал добавить values() после select_related().Нет, уходи.Затем я попробовал различные перестановки каждого в разных позициях запроса.Близко, но не совсем.

В итоге я «истощился» и просто использовал чистый SQL, поскольку уже знал, как писать SQL-запрос.

def coins_by_country(request, country_name):
    country = get_object_or_404(Country, name=country_name)
    cursor = connection.cursor()
    cursor.execute('SELECT count(*), face_value, collection_currency.name FROM collection_collectible, collection_currency WHERE collection_collectible.currency_type_id = collection_currency.id AND country_id=%s AND type=1 group by face_value, collection_currency.name', [country.id] )
    coin_values = cursor.fetchall()
    return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )

Если есть способ сформулировать этот точный запрос на языке набора запросов Django, мне было бы интересно узнать.Я полагаю, что SQL-соединение со счетчиком и группировкой по двум столбцам не является чем-то очень редким, поэтому я был бы удивлен, если бы не было чистого способа.

Другие советы

Вы не можете сделать это с values().Но нет необходимости использовать это — вы можете просто получить фактическое Collectible объекты, и каждый из них будет иметь currency_type атрибут, который будет соответствующим связанным объектом.

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

Соединив это, вы получите:

coin_values = Collectible.objects.filter(country=country.id, 
                    type=1).extra(
                    select={'count': 'count(1)'}, 
                    order_by=['-count']
                ).select_related()

Вы пробовали select_related()? http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4

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

Кроме того, я не думаю, что вам нужно указывать в фильтре Country=country.id, просто Country=country, но я не уверен, какая разница, кроме меньшего количества ввода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top