Opened 16 years ago

Closed 14 years ago

#8378 closed (fixed)

Generic views cache-like behavior

Reported by: ovidiup Owned by: nobody
Component: Documentation Version: dev
Severity: Keywords: generic view cache
Cc: semente@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Sometimes the generic views will behave like they are caching the data from the queryset argument. This happens when the queryset is passed through the info_dict dictionary and the queryset is filtered using a callable. The result of the callable is cached in the where clause. When the generic view is executed the callable from the filter is not invoked again.
See this blog post for more details, example and work-around: http://pascut.com/2008/08/16/django-generic-views-cache-behavior/
One of the following things should be done:

  1. The result of the callables should not be cached in the where clause; the callables should be invoked just before the query is sent to the database or
  2. The documentation should mention this as a limitation

Change History (8)

comment:1 by anonymous, 16 years ago

Cc: ovidiup@… removed

comment:2 by Malcolm Tredinnick, 16 years ago

Component: Generic viewsDocumentation
Triage Stage: UnreviewedAccepted

A clarification in the documentation might be worthwhile here if it can be written so that it's not too long (this is an edge-case so should be very incidental to the main description of things). Something to the effect that callables in filters are evaluated exactly once. We can't really change things so that that doesn't happen, since it would only be to support a situation like this and would introduce a lot of extra complexity.

comment:3 by Guilherme M. Gondim <semente@…>, 16 years ago

Cc: semente@… added

comment:4 by Jacob, 16 years ago

milestone: 1.0 maybepost-1.0

comment:5 by zbyte64, 16 years ago

Couldn't we make the generic views check if the queryset parameter is callable, and if so, call it per request. So an example would be:

url(r'$', 'django.views.generic.list_detail.object_list', {'queryset':ClassifiedCategory.objects.all(),}, 'classifieds'),

would then become:

url(r'$', 'django.views.generic.list_detail.object_list', {'queryset':ClassifiedCategory.objects.all,}, 'classifieds'),

Furthermore, the queyset is not callable. Alternatively, the generic view could do a hasattr(queryset, '_clone') and call based off that.

comment:6 by (none), 16 years ago

milestone: post-1.0

Milestone post-1.0 deleted

comment:7 by zbyte64, 15 years ago

Ignore my previous comment. Seems that is a different bug and have been fixed, this issue deals more with querysets. See code below:

>>> from django.contrib.auth.models import User
>>> import datetime, time
>>> qs = User.objects.all().filter(last_login__lte=datetime.datetime.now)
>>> qs._clone().query.as_sql()
('SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`last_login` <= %s ', (u'2009-06-26 16:44:41',))
>>> time.sleep(5)
>>> qs._clone().query.as_sql()
('SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`last_login` <= %s ', (u'2009-06-26 16:44:41',))

As you can see the query didn't change even though we passed a callable in and used _clone. It seem the queryset allows callables to be passed but are immediately evaluated. The callables should be lazy in their evaluation and the value return by a callable should not be passed on when it is clone, rather the callable itself should be passed

comment:8 by Russell Keith-Magee, 14 years ago

Resolution: fixed
Status: newclosed

Function-based generic views were deprecated by the introduction of class-based views in [14254]. Class-based views should solve this problem.

Note: See TracTickets for help on using tickets.
Back to Top