~ubuntu-branches/ubuntu/quantal/python-django/quantal

« back to all changes in this revision

Viewing changes to tests/regressiontests/aggregation_regress/models.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.1.8 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090729112628-pg09ino8sz0sj21t
Tags: 1.1-1
* New upstream release.
* Merge from experimental:
  - Ship FastCGI initscript and /etc/default file in python-django's examples
    directory (Closes: #538863)
  - Drop "05_10539-sphinx06-compatibility.diff"; it has been applied
    upstream.
  - Bump Standards-Version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# coding: utf-8
 
2
import pickle
 
3
 
 
4
from django.db import connection, models
 
5
from django.conf import settings
 
6
 
 
7
try:
 
8
    sorted
 
9
except NameError:
 
10
    from django.utils.itercompat import sorted      # For Python 2.3
 
11
 
 
12
class Author(models.Model):
 
13
    name = models.CharField(max_length=100)
 
14
    age = models.IntegerField()
 
15
    friends = models.ManyToManyField('self', blank=True)
 
16
 
 
17
    def __unicode__(self):
 
18
        return self.name
 
19
 
 
20
class Publisher(models.Model):
 
21
    name = models.CharField(max_length=255)
 
22
    num_awards = models.IntegerField()
 
23
 
 
24
    def __unicode__(self):
 
25
        return self.name
 
26
 
 
27
class Book(models.Model):
 
28
    isbn = models.CharField(max_length=9)
 
29
    name = models.CharField(max_length=255)
 
30
    pages = models.IntegerField()
 
31
    rating = models.FloatField()
 
32
    price = models.DecimalField(decimal_places=2, max_digits=6)
 
33
    authors = models.ManyToManyField(Author)
 
34
    contact = models.ForeignKey(Author, related_name='book_contact_set')
 
35
    publisher = models.ForeignKey(Publisher)
 
36
    pubdate = models.DateField()
 
37
 
 
38
    class Meta:
 
39
        ordering = ('name',)
 
40
 
 
41
    def __unicode__(self):
 
42
        return self.name
 
43
 
 
44
class Store(models.Model):
 
45
    name = models.CharField(max_length=255)
 
46
    books = models.ManyToManyField(Book)
 
47
    original_opening = models.DateTimeField()
 
48
    friday_night_closing = models.TimeField()
 
49
 
 
50
    def __unicode__(self):
 
51
        return self.name
 
52
 
 
53
class Entries(models.Model):
 
54
    EntryID = models.AutoField(primary_key=True, db_column='Entry ID')
 
55
    Entry = models.CharField(unique=True, max_length=50)
 
56
    Exclude = models.BooleanField()
 
57
 
 
58
class Clues(models.Model):
 
59
    ID = models.AutoField(primary_key=True)
 
60
    EntryID = models.ForeignKey(Entries, verbose_name='Entry', db_column = 'Entry ID')
 
61
    Clue = models.CharField(max_length=150)
 
62
 
 
63
class HardbackBook(Book):
 
64
    weight = models.FloatField()
 
65
 
 
66
    def __unicode__(self):
 
67
        return "%s (hardback): %s" % (self.name, self.weight)
 
68
 
 
69
__test__ = {'API_TESTS': """
 
70
>>> from django.core import management
 
71
>>> from django.db.models import get_app, F
 
72
 
 
73
# Reset the database representation of this app.
 
74
# This will return the database to a clean initial state.
 
75
>>> management.call_command('flush', verbosity=0, interactive=False)
 
76
 
 
77
>>> from django.db.models import Avg, Sum, Count, Max, Min, StdDev, Variance
 
78
 
 
79
# Ordering requests are ignored
 
80
>>> Author.objects.all().order_by('name').aggregate(Avg('age'))
 
81
{'age__avg': 37.4...}
 
82
 
 
83
# Implicit ordering is also ignored
 
84
>>> Book.objects.all().aggregate(Sum('pages'))
 
85
{'pages__sum': 3703}
 
86
 
 
87
# Baseline results
 
88
>>> Book.objects.all().aggregate(Sum('pages'), Avg('pages'))
 
89
{'pages__sum': 3703, 'pages__avg': 617.1...}
 
90
 
 
91
# Empty values query doesn't affect grouping or results
 
92
>>> Book.objects.all().values().aggregate(Sum('pages'), Avg('pages'))
 
93
{'pages__sum': 3703, 'pages__avg': 617.1...}
 
94
 
 
95
# Aggregate overrides extra selected column
 
96
>>> Book.objects.all().extra(select={'price_per_page' : 'price / pages'}).aggregate(Sum('pages'))
 
97
{'pages__sum': 3703}
 
98
 
 
99
# Annotations get combined with extra select clauses
 
100
>>> sorted(Book.objects.all().annotate(mean_auth_age=Avg('authors__age')).extra(select={'manufacture_cost' : 'price * .5'}).get(pk=2).__dict__.items())
 
101
[('contact_id', 3), ('id', 2), ('isbn', u'067232959'), ('manufacture_cost', ...11.545...), ('mean_auth_age', 45.0), ('name', u'Sams Teach Yourself Django in 24 Hours'), ('pages', 528), ('price', Decimal("23.09")), ('pubdate', datetime.date(2008, 3, 3)), ('publisher_id', 2), ('rating', 3.0)]
 
102
 
 
103
# Order of the annotate/extra in the query doesn't matter
 
104
>>> sorted(Book.objects.all().extra(select={'manufacture_cost' : 'price * .5'}).annotate(mean_auth_age=Avg('authors__age')).get(pk=2).__dict__.items())
 
105
[('contact_id', 3), ('id', 2), ('isbn', u'067232959'), ('manufacture_cost', ...11.545...), ('mean_auth_age', 45.0), ('name', u'Sams Teach Yourself Django in 24 Hours'), ('pages', 528), ('price', Decimal("23.09")), ('pubdate', datetime.date(2008, 3, 3)), ('publisher_id', 2), ('rating', 3.0)]
 
106
 
 
107
# Values queries can be combined with annotate and extra
 
108
>>> sorted(Book.objects.all().annotate(mean_auth_age=Avg('authors__age')).extra(select={'manufacture_cost' : 'price * .5'}).values().get(pk=2).items())
 
109
[('contact_id', 3), ('id', 2), ('isbn', u'067232959'), ('manufacture_cost', ...11.545...), ('mean_auth_age', 45.0), ('name', u'Sams Teach Yourself Django in 24 Hours'), ('pages', 528), ('price', Decimal("23.09")), ('pubdate', datetime.date(2008, 3, 3)), ('publisher_id', 2), ('rating', 3.0)]
 
110
 
 
111
# The order of the (empty) values, annotate and extra clauses doesn't matter
 
112
>>> sorted(Book.objects.all().values().annotate(mean_auth_age=Avg('authors__age')).extra(select={'manufacture_cost' : 'price * .5'}).get(pk=2).items())
 
113
[('contact_id', 3), ('id', 2), ('isbn', u'067232959'), ('manufacture_cost', ...11.545...), ('mean_auth_age', 45.0), ('name', u'Sams Teach Yourself Django in 24 Hours'), ('pages', 528), ('price', Decimal("23.09")), ('pubdate', datetime.date(2008, 3, 3)), ('publisher_id', 2), ('rating', 3.0)]
 
114
 
 
115
# If the annotation precedes the values clause, it won't be included
 
116
# unless it is explicitly named
 
117
>>> sorted(Book.objects.all().annotate(mean_auth_age=Avg('authors__age')).extra(select={'price_per_page' : 'price / pages'}).values('name').get(pk=1).items())
 
118
[('name', u'The Definitive Guide to Django: Web Development Done Right')]
 
119
 
 
120
>>> sorted(Book.objects.all().annotate(mean_auth_age=Avg('authors__age')).extra(select={'price_per_page' : 'price / pages'}).values('name','mean_auth_age').get(pk=1).items())
 
121
[('mean_auth_age', 34.5), ('name', u'The Definitive Guide to Django: Web Development Done Right')]
 
122
 
 
123
# If an annotation isn't included in the values, it can still be used in a filter
 
124
>>> Book.objects.annotate(n_authors=Count('authors')).values('name').filter(n_authors__gt=2)
 
125
[{'name': u'Python Web Development with Django'}]
 
126
 
 
127
# The annotations are added to values output if values() precedes annotate()
 
128
>>> sorted(Book.objects.all().values('name').annotate(mean_auth_age=Avg('authors__age')).extra(select={'price_per_page' : 'price / pages'}).get(pk=1).items())
 
129
[('mean_auth_age', 34.5), ('name', u'The Definitive Guide to Django: Web Development Done Right')]
 
130
 
 
131
# Check that all of the objects are getting counted (allow_nulls) and that values respects the amount of objects
 
132
>>> len(Author.objects.all().annotate(Avg('friends__age')).values())
 
133
9
 
134
 
 
135
# Check that consecutive calls to annotate accumulate in the query
 
136
>>> Book.objects.values('price').annotate(oldest=Max('authors__age')).order_by('oldest', 'price').annotate(Max('publisher__num_awards'))
 
137
[{'price': Decimal("30..."), 'oldest': 35, 'publisher__num_awards__max': 3}, {'price': Decimal("29.69"), 'oldest': 37, 'publisher__num_awards__max': 7}, {'price': Decimal("23.09"), 'oldest': 45, 'publisher__num_awards__max': 1}, {'price': Decimal("75..."), 'oldest': 57, 'publisher__num_awards__max': 9}, {'price': Decimal("82.8..."), 'oldest': 57, 'publisher__num_awards__max': 7}]
 
138
 
 
139
# Aggregates can be composed over annotations.
 
140
# The return type is derived from the composed aggregate
 
141
>>> Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('pages'), Max('price'), Sum('num_authors'), Avg('num_authors'))
 
142
{'num_authors__sum': 10, 'num_authors__avg': 1.66..., 'pages__max': 1132, 'price__max': Decimal("82.80")}
 
143
 
 
144
# Bad field requests in aggregates are caught and reported
 
145
>>> Book.objects.all().aggregate(num_authors=Count('foo'))
 
146
Traceback (most recent call last):
 
147
...
 
148
FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
 
149
 
 
150
>>> Book.objects.all().annotate(num_authors=Count('foo'))
 
151
Traceback (most recent call last):
 
152
...
 
153
FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store
 
154
 
 
155
>>> Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo'))
 
156
Traceback (most recent call last):
 
157
...
 
158
FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, contact, hardbackbook, id, isbn, name, pages, price, pubdate, publisher, rating, store, num_authors
 
159
 
 
160
# Old-style count aggregations can be mixed with new-style
 
161
>>> Book.objects.annotate(num_authors=Count('authors')).count()
 
162
6
 
163
 
 
164
# Non-ordinal, non-computed Aggregates over annotations correctly inherit
 
165
# the annotation's internal type if the annotation is ordinal or computed
 
166
>>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Max('num_authors'))
 
167
{'num_authors__max': 3}
 
168
 
 
169
>>> Publisher.objects.annotate(avg_price=Avg('book__price')).aggregate(Max('avg_price'))
 
170
{'avg_price__max': 75.0...}
 
171
 
 
172
# Aliases are quoted to protected aliases that might be reserved names
 
173
>>> Book.objects.aggregate(number=Max('pages'), select=Max('pages'))
 
174
{'number': 1132, 'select': 1132}
 
175
 
 
176
# Regression for #10064: select_related() plays nice with aggregates
 
177
>>> Book.objects.select_related('publisher').annotate(num_authors=Count('authors')).values()[0]
 
178
{'rating': 4.0, 'isbn': u'013790395', 'name': u'Artificial Intelligence: A Modern Approach', 'pubdate': datetime.date(1995, 1, 15), 'price': Decimal("82.8..."), 'contact_id': 8, 'id': 5, 'num_authors': 2, 'publisher_id': 3, 'pages': 1132}
 
179
 
 
180
# Regression for #10010: exclude on an aggregate field is correctly negated
 
181
>>> len(Book.objects.annotate(num_authors=Count('authors')))
 
182
6
 
183
>>> len(Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=2))
 
184
1
 
185
>>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__gt=2))
 
186
5
 
187
 
 
188
>>> len(Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__lt=3).exclude(num_authors__lt=2))
 
189
2
 
190
>>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3))
 
191
2
 
192
 
 
193
# Aggregates can be used with F() expressions
 
194
# ... where the F() is pushed into the HAVING clause
 
195
>>> Publisher.objects.annotate(num_books=Count('book')).filter(num_books__lt=F('num_awards')/2).order_by('name').values('name','num_books','num_awards')
 
196
[{'num_books': 1, 'name': u'Morgan Kaufmann', 'num_awards': 9}, {'num_books': 2, 'name': u'Prentice Hall', 'num_awards': 7}]
 
197
 
 
198
>>> Publisher.objects.annotate(num_books=Count('book')).exclude(num_books__lt=F('num_awards')/2).order_by('name').values('name','num_books','num_awards')
 
199
[{'num_books': 2, 'name': u'Apress', 'num_awards': 3}, {'num_books': 0, 'name': u"Jonno's House of Books", 'num_awards': 0}, {'num_books': 1, 'name': u'Sams', 'num_awards': 1}]
 
200
 
 
201
# ... and where the F() references an aggregate
 
202
>>> Publisher.objects.annotate(num_books=Count('book')).filter(num_awards__gt=2*F('num_books')).order_by('name').values('name','num_books','num_awards')
 
203
[{'num_books': 1, 'name': u'Morgan Kaufmann', 'num_awards': 9}, {'num_books': 2, 'name': u'Prentice Hall', 'num_awards': 7}]
 
204
 
 
205
>>> Publisher.objects.annotate(num_books=Count('book')).exclude(num_books__lt=F('num_awards')/2).order_by('name').values('name','num_books','num_awards')
 
206
[{'num_books': 2, 'name': u'Apress', 'num_awards': 3}, {'num_books': 0, 'name': u"Jonno's House of Books", 'num_awards': 0}, {'num_books': 1, 'name': u'Sams', 'num_awards': 1}]
 
207
 
 
208
# Tests on fields with non-default table and column names.
 
209
>>> Clues.objects.values('EntryID__Entry').annotate(Appearances=Count('EntryID'), Distinct_Clues=Count('Clue', distinct=True))
 
210
[]
 
211
 
 
212
>>> Entries.objects.annotate(clue_count=Count('clues__ID'))
 
213
[]
 
214
 
 
215
# Regression for #10089: Check handling of empty result sets with aggregates
 
216
>>> Book.objects.filter(id__in=[]).count()
 
217
0
 
218
 
 
219
>>> Book.objects.filter(id__in=[]).aggregate(num_authors=Count('authors'), avg_authors=Avg('authors'), max_authors=Max('authors'), max_price=Max('price'), max_rating=Max('rating'))
 
220
{'max_authors': None, 'max_rating': None, 'num_authors': 0, 'avg_authors': None, 'max_price': None}
 
221
 
 
222
>>> Publisher.objects.filter(pk=5).annotate(num_authors=Count('book__authors'), avg_authors=Avg('book__authors'), max_authors=Max('book__authors'), max_price=Max('book__price'), max_rating=Max('book__rating')).values()
 
223
[{'max_authors': None, 'name': u"Jonno's House of Books", 'num_awards': 0, 'max_price': None, 'num_authors': 0, 'max_rating': None, 'id': 5, 'avg_authors': None}]
 
224
 
 
225
# Regression for #10113 - Fields mentioned in order_by() must be included in the GROUP BY.
 
226
# This only becomes a problem when the order_by introduces a new join.
 
227
>>> Book.objects.annotate(num_authors=Count('authors')).order_by('publisher__name', 'name')
 
228
[<Book: Practical Django Projects>, <Book: The Definitive Guide to Django: Web Development Done Right>, <Book: Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp>, <Book: Artificial Intelligence: A Modern Approach>, <Book: Python Web Development with Django>, <Book: Sams Teach Yourself Django in 24 Hours>]
 
229
 
 
230
# Regression for #10127 - Empty select_related() works with annotate
 
231
>>> books = Book.objects.all().filter(rating__lt=4.5).select_related().annotate(Avg('authors__age'))
 
232
>>> sorted([(b.name, b.authors__age__avg, b.publisher.name, b.contact.name) for b in books])
 
233
[(u'Artificial Intelligence: A Modern Approach', 51.5, u'Prentice Hall', u'Peter Norvig'), (u'Practical Django Projects', 29.0, u'Apress', u'James Bennett'), (u'Python Web Development with Django', 30.3..., u'Prentice Hall', u'Jeffrey Forcier'), (u'Sams Teach Yourself Django in 24 Hours', 45.0, u'Sams', u'Brad Dayley')]
 
234
 
 
235
# Regression for #10132 - If the values() clause only mentioned extra(select=) columns, those columns are used for grouping
 
236
>>> Book.objects.extra(select={'pub':'publisher_id'}).values('pub').annotate(Count('id')).order_by('pub')
 
237
[{'pub': 1, 'id__count': 2}, {'pub': 2, 'id__count': 1}, {'pub': 3, 'id__count': 2}, {'pub': 4, 'id__count': 1}]
 
238
 
 
239
>>> Book.objects.extra(select={'pub':'publisher_id','foo':'pages'}).values('pub').annotate(Count('id')).order_by('pub')
 
240
[{'pub': 1, 'id__count': 2}, {'pub': 2, 'id__count': 1}, {'pub': 3, 'id__count': 2}, {'pub': 4, 'id__count': 1}]
 
241
 
 
242
# Regression for #10182 - Queries with aggregate calls are correctly realiased when used in a subquery
 
243
>>> ids = Book.objects.filter(pages__gt=100).annotate(n_authors=Count('authors')).filter(n_authors__gt=2).order_by('n_authors')
 
244
>>> Book.objects.filter(id__in=ids)
 
245
[<Book: Python Web Development with Django>]
 
246
 
 
247
# Regression for #10197 -- Queries with aggregates can be pickled.
 
248
# First check that pickling is possible at all. No crash = success
 
249
>>> qs = Book.objects.annotate(num_authors=Count('authors'))
 
250
>>> out = pickle.dumps(qs)
 
251
 
 
252
# Then check that the round trip works.
 
253
>>> query = qs.query.as_sql()[0]
 
254
>>> select_fields = qs.query.select_fields
 
255
>>> query2 = pickle.loads(pickle.dumps(qs))
 
256
>>> query2.query.as_sql()[0] == query
 
257
True
 
258
>>> query2.query.select_fields = select_fields
 
259
 
 
260
# Regression for #10199 - Aggregate calls clone the original query so the original query can still be used
 
261
>>> books = Book.objects.all()
 
262
>>> _ = books.aggregate(Avg('authors__age'))
 
263
>>> books.all()
 
264
[<Book: Artificial Intelligence: A Modern Approach>, <Book: Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp>, <Book: Practical Django Projects>, <Book: Python Web Development with Django>, <Book: Sams Teach Yourself Django in 24 Hours>, <Book: The Definitive Guide to Django: Web Development Done Right>]
 
265
 
 
266
# Regression for #10248 - Annotations work with DateQuerySets
 
267
>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors=2).dates('pubdate', 'day')
 
268
[datetime.datetime(1995, 1, 15, 0, 0), datetime.datetime(2007, 12, 6, 0, 0)]
 
269
 
 
270
# Regression for #10290 - extra selects with parameters can be used for
 
271
# grouping.
 
272
>>> qs = Book.objects.all().annotate(mean_auth_age=Avg('authors__age')).extra(select={'sheets' : '(pages + %s) / %s'}, select_params=[1, 2]).order_by('sheets').values('sheets')
 
273
>>> [int(x['sheets']) for x in qs]
 
274
[150, 175, 224, 264, 473, 566]
 
275
 
 
276
# Regression for 10425 - annotations don't get in the way of a count() clause
 
277
>>> Book.objects.values('publisher').annotate(Count('publisher')).count()
 
278
4
 
279
 
 
280
>>> Book.objects.annotate(Count('publisher')).values('publisher').count()
 
281
6
 
282
 
 
283
>>> publishers = Publisher.objects.filter(id__in=(1,2))
 
284
>>> publishers
 
285
[<Publisher: Apress>, <Publisher: Sams>]
 
286
 
 
287
>>> publishers = publishers.annotate(n_books=models.Count('book'))
 
288
>>> publishers[0].n_books
 
289
2
 
290
 
 
291
>>> publishers
 
292
[<Publisher: Apress>, <Publisher: Sams>]
 
293
 
 
294
>>> books = Book.objects.filter(publisher__in=publishers)
 
295
>>> books
 
296
[<Book: Practical Django Projects>, <Book: Sams Teach Yourself Django in 24 Hours>, <Book: The Definitive Guide to Django: Web Development Done Right>]
 
297
 
 
298
>>> publishers
 
299
[<Publisher: Apress>, <Publisher: Sams>]
 
300
 
 
301
 
 
302
# Regression for 10666 - inherited fields work with annotations and aggregations
 
303
>>> HardbackBook.objects.aggregate(n_pages=Sum('book_ptr__pages'))
 
304
{'n_pages': 2078}
 
305
 
 
306
>>> HardbackBook.objects.aggregate(n_pages=Sum('pages'))
 
307
{'n_pages': 2078}
 
308
 
 
309
>>> HardbackBook.objects.annotate(n_authors=Count('book_ptr__authors')).values('name','n_authors')
 
310
[{'n_authors': 2, 'name': u'Artificial Intelligence: A Modern Approach'}, {'n_authors': 1, 'name': u'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp'}]
 
311
 
 
312
>>> HardbackBook.objects.annotate(n_authors=Count('authors')).values('name','n_authors')
 
313
[{'n_authors': 2, 'name': u'Artificial Intelligence: A Modern Approach'}, {'n_authors': 1, 'name': u'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp'}]
 
314
 
 
315
# Regression for #10766 - Shouldn't be able to reference an aggregate fields in an an aggregate() call.
 
316
>>> Book.objects.all().annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age'))
 
317
Traceback (most recent call last):
 
318
...
 
319
FieldError: Cannot compute Avg('mean_age'): 'mean_age' is an aggregate
 
320
 
 
321
"""
 
322
}
 
323
 
 
324
def run_stddev_tests():
 
325
    """Check to see if StdDev/Variance tests should be run.
 
326
 
 
327
    Stddev and Variance are not guaranteed to be available for SQLite, and
 
328
    are not available for PostgreSQL before 8.2.
 
329
    """
 
330
    if settings.DATABASE_ENGINE == 'sqlite3':
 
331
        return False
 
332
 
 
333
    class StdDevPop(object):
 
334
        sql_function = 'STDDEV_POP'
 
335
 
 
336
    try:
 
337
        connection.ops.check_aggregate_support(StdDevPop())
 
338
    except:
 
339
        return False
 
340
    return True
 
341
 
 
342
if run_stddev_tests():
 
343
    __test__['API_TESTS'] += """
 
344
>>> Book.objects.aggregate(StdDev('pages'))
 
345
{'pages__stddev': 311.46...}
 
346
 
 
347
>>> Book.objects.aggregate(StdDev('rating'))
 
348
{'rating__stddev': 0.60...}
 
349
 
 
350
>>> Book.objects.aggregate(StdDev('price'))
 
351
{'price__stddev': 24.16...}
 
352
 
 
353
 
 
354
>>> Book.objects.aggregate(StdDev('pages', sample=True))
 
355
{'pages__stddev': 341.19...}
 
356
 
 
357
>>> Book.objects.aggregate(StdDev('rating', sample=True))
 
358
{'rating__stddev': 0.66...}
 
359
 
 
360
>>> Book.objects.aggregate(StdDev('price', sample=True))
 
361
{'price__stddev': 26.46...}
 
362
 
 
363
 
 
364
>>> Book.objects.aggregate(Variance('pages'))
 
365
{'pages__variance': 97010.80...}
 
366
 
 
367
>>> Book.objects.aggregate(Variance('rating'))
 
368
{'rating__variance': 0.36...}
 
369
 
 
370
>>> Book.objects.aggregate(Variance('price'))
 
371
{'price__variance': 583.77...}
 
372
 
 
373
 
 
374
>>> Book.objects.aggregate(Variance('pages', sample=True))
 
375
{'pages__variance': 116412.96...}
 
376
 
 
377
>>> Book.objects.aggregate(Variance('rating', sample=True))
 
378
{'rating__variance': 0.44...}
 
379
 
 
380
>>> Book.objects.aggregate(Variance('price', sample=True))
 
381
{'price__variance': 700.53...}
 
382
 
 
383
 
 
384
"""