Разница между аннотированным и агрегатным методами в Django? - PullRequest
91 голосов
/ 02 ноября 2011

У Джанго QuerySet есть два метода, annotate и aggregate.В документации сказано, что:

В отличие от aggregate (), annotate () не является терминальным предложением.Результатом предложения annotate () является QuerySet.

Есть ли какая-либо другая разница между ними?Если нет, то почему aggregate существует?

Ответы [ 3 ]

148 голосов
/ 02 ноября 2011

Я бы сосредоточился на примере запросов, а не на вашей цитате из документации.Aggregate вычисляет значения для всего запроса.Annotate вычисляет итоговые значения для каждого элемента в наборе запросов.

Агрегирование

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

Возвращает словарь, содержащий среднюю цену все книги в наборе запросов.

Аннотация

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

q - это набор запросов книг, но каждая книга помечена числом авторов.

18 голосов
/ 02 ноября 2011

В этом главное отличие, но агрегаты также работают в большем масштабе, чем аннотации. Аннотации по своей сути связаны с отдельными элементами в наборе запросов. Если вы запустите аннотацию Count в поле типа «многие ко многим», вы получите отдельный счетчик для каждого члена набора запросов (в качестве добавленного атрибута). Однако, если вы сделаете то же самое с агрегацией, она попытается подсчитать все отношения на каждом элементе набора запросов, даже дублировать их, и вернуть их как одно значение.

11 голосов
/ 31 августа 2017

Агрегирование Агрегирование значений результата (сводки) по всему QuerySet.Агрегат работает над набором строк, чтобы получить одно значение из набора строк (например, сумма всех цен в наборе строк).Агрегат применяется ко всему QuerySet и генерирует итоговые (итоговые) значения по всему QuerySet.

В модели:

class Books(models.Model):
    name = models.CharField(max_length=100)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=3)

В оболочке:

>>> Books.objects.all().aggregate(Avg('price'))
# Above code will give the Average of the price Column 
>>> {'price__avg': 34.35}

Annotate Annotate создает независимую сводку для каждого объекта в QuerySet. (Можно сказать, что он выполняет итерацию каждого объекта в QuerySet и применяет операцию)

В модели:

class Video(models.Model):
    name = models.CharField(max_length=52, verbose_name='Name')
    video = models.FileField(upload_to=document_path, verbose_name='Upload 
               video')
    created_by = models.ForeignKey(User, verbose_name='Created by', 
                       related_name="create_%(class)s")
    user_likes = models.ManyToManyField(UserProfile, null=True, 
                  blank=True, help_text='User can like once', 
                         verbose_name='Like by')

В представлении:

videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True)

В представлении этогобудет подсчитывать лайки за каждое видео

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