Django аннотирует набор запроса количеством на подзапросе

Его уже сказал несколько раз, но http://www.proggyfonts.com/ является просто потрясающим. Я - большой поклонник Proggy Чистая Разрезанная Нулевая Полужирная Пунктуация. Я делаю большую часть своей работы в c#, таким образом, полужирная пунктуация очень хороша для него.

15
задан Evgeny 5 December 2009 в 01:25
поделиться

2 ответа

Если посмотреть на функцию add_aggregate в django / db / models / sql / query.py , объекты запроса не будут приняты в качестве входных значений.

К сожалению, в настоящее время в Django нет прямого способа агрегировать / аннотировать, что составляет набор запросов, особенно тот, который каким-то образом дополнительно фильтруется.

Предполагая следующие модели:

class Item(models.Model):
    name = models.CharField(max_length=32)

class Tag(models.Model):
    itemfk = models.ForeignKey(Item, related_name='tags')
    name = models.CharField(max_length=32)

class FavoritedTag(models.Model):
    user = models.ForeignKey(User)
    tag = models.ForeignKey(Tag)

Кроме того, вы не можете аннотировать набор запросов для полей, определенных с помощью .extra () .

Можно перейти к SQL в views.py следующим образом:

from testing.models import Item, Tag, FavoritedTag
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.utils.datastructures import SortedDict

@login_required
def interest_level(request):
    ruid = request.user.id

    qs = Item.objects.extra(
        select = SortedDict([
            ('interest_level', 'SELECT COUNT(*) FROM testing_favoritedtag, testing_tag \
            WHERE testing_favoritedtag.user_id = %s \
            AND testing_favoritedtag.tag_id = testing_tag.id \
            AND testing_tag.itemfk_id = testing_item.id'),
        ]),
        select_params = (str(ruid),)
    )

    return render_to_response('testing/interest_level.html', {'qs': qs})

Шаблон:

{% for item in qs %}
    name: {{ item.name }}, level: {{ item.interest_level }}<br>
{% endfor %}

Я тестировал это с помощью MySQL5 . Поскольку я не эксперт по SQL, мне было бы любопытно, как здесь оптимизировать или есть ли другой способ «уменьшить» количество SQL.

10
ответ дан 1 December 2019 в 04:53
поделиться

Если вы хотите избежать падения до RAW SQL, другой способ коже Этот кот будет использовать метод модели, который затем даст вам новый атрибут модели для использования в ваших шаблонах Отказ Не пропущенная, но что-то вроде этого в вашей модели тегов должна работать:

class Tag(models.Model):
    itemfk = models.ForeignKey(Item, related_name='tags')
    name = models.CharField(max_length=32)

    def get_favetag_count(self):
        """
        Calculate the number of times the current user has favorited a particular tag
        """

        favetag_count = FavoritedTag.objects.filter(tag=self,user=request.user).count()
        return favetag_count

Тогда в вашем шаблоне вы можете использовать что-то вроде:

{{tag}} ({{tag.get_favetag_count}})

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

1
ответ дан 1 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: