Как получить связанные объекты при вызове extra().values() в Django?
-
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, но я не уверен, какая разница, кроме меньшего количества ввода.