Opened 7 years ago

Closed 5 years ago

#8378 closed (fixed)

Generic views cache-like behavior

Reported by: ovidiup Owned by: nobody
Component: Documentation Version: master
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: UI/UX:

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 Changed 7 years ago by anonymous

  • Cc ovidiup@… removed
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 7 years ago by mtredinnick

  • Component changed from Generic views to Documentation
  • Triage Stage changed from Unreviewed to Accepted

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 Changed 7 years ago by Guilherme M. Gondim <semente@…>

  • Cc semente@… added

comment:4 Changed 7 years ago by jacob

  • milestone changed from 1.0 maybe to post-1.0

comment:5 Changed 7 years ago by zbyte64

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 Changed 7 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

comment:7 Changed 6 years ago by zbyte64

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 Changed 5 years ago by russellm

  • Resolution set to fixed
  • Status changed from new to closed

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