Permalink
Browse files

- updated requirements, docs

  • Loading branch information...
1 parent 7e6e181 commit 2f64f602bdf0758ed43383e72ee4cdc6124e3d7f @outofculture outofculture committed Feb 21, 2012
Showing with 31 additions and 25 deletions.
  1. +24 −19 README.rst
  2. +1 −2 setup.cfg
  3. +6 −4 setup.py
View
@@ -4,16 +4,15 @@ Django Cached Field
Introduction
------------
-Using Django ORM and Celery, keep expensive-to-calculate attributes
-up-to-date.
+Using Django ORM and Celery, cache expensive-to-calculate attributes.
Example
-------
Say you have a slow method on one of your models::
class Lamppost(models.Model):
-
+ # ...
@property
def slow_full_name(self):
sleep(30)
@@ -28,6 +27,7 @@ from the model mixin and rename our method appropriately::
from django_cached_field import CachedIntegerField, ModelWithCachedFields
class Lamppost(models.Model, ModelWithCachedFields):
+ # ...
slow_full_name = CachedTextField(null=True)
def calculate_slow_full_name(self):
@@ -48,24 +48,26 @@ seconds the first time it gets called for a given record, but from
then on, it'll be nigh instant. Of course, at this point, it will
never change after that first call.
-The remaining important piece of the puzzle is to invalidate our
-cache. Thoses constituent fields are probably changed in some views.py
-(this could be more clever about noticing if the relevant values are
-updated)::
+The remaining important piece of the puzzle is to invalidate our cache
+using ``flag_slow_full_name_as_stale``. It is probably changed in some
+views.py (this example code could be more clever about noticing if the
+relevant values are updated)::
- @render_to("lamppost/edit.html")
+ @render_to('lamppost/edit.html')
def edit(request, lamppost_id):
lamppost = Lamppost.objects.get(pk=lamppost_id)
if request.METHOD == 'POST':
form = LamppostForm(request.POST)
if form.is_valid():
form.save()
form.instance.flag_slow_full_name_as_stale()
+ return HttpResponseRedirect(
+ reverse('lamppost_view', args=(lamppost.pk,)))
else:
form = LamppostForm()
return {'form': form, 'lamppost': lamppost}
-**This is the hardest part as the developer!** Caching requires you
+**This is the hardest part as the developer.** Caching requires you
hunt down every place the value could be changed and calling that
``flag_slow_full_name_as_stale`` method. Is country assigned a random
new value every morning at cron'o'clock? That flag had best be stale
@@ -82,13 +84,15 @@ You can make things easy on yourself::
pip install django-cached-field
-Or, for a manual installation, you can clone the repo and install it using python and setup.py::
+Or, for a manual installation, you can clone the repo and install it
+using python and setup.py::
git clone git://github.com/aquameta/django-cached-field.git
cd django-cached-field/
python setup.py install
-Tested with django 1.3.1, celery 2.3.1, django-celery 2.3.3.
+Tested with django 1.3.1, celery 2.3.1, and django-celery 2.3.3, but I
+would entertain other minimums if someone was willing to test them.
Configuration
-------------
@@ -101,23 +105,24 @@ sure it's a registered app, make sure celery sees its tasks file::
One change is optional: whether recalculation should happen when
flagged as stale (default) or be left to the next time the attribute
-is accessed. This is useful for testing environments where you don't
-care that your cached values are invalid. Note that in this situation,
-you wouldn't need celery. ::
+is accessed. This is useful for optimizing testing environments where
+you don't care that your cached values are invalid or that the expense
+of calculation is applied to a user. Note that, in this situation, you
+wouldn't need celery. ::
CACHED_FIELD_EAGER_RECALCULATION = True # or False for testing environments
This is a global option, so individual exceptions should instead be
-handled by passing the *and_recalculate* argument to the
-*flag_FIELD_as_stale* call.
+handled by passing the ``and_recalculate`` argument to the
+``flag_FIELD_as_stale`` call.
Caveats
-------
* Race condition if you flag a field as stale in a db transaction that takes longer to complete than the celery job takes to be called.
-* All ORM methods (e.g. order_by, filter) need to use cached_FIELD.
-* recalculate_FIELD uses .update(cached_FIELD= to set the value.
-* flag_FIELD_as_stale uses .update, as well.
+* All ORM methods (e.g. ``order_by``, ``filter``) can only access this data through ``cached_FIELD``.
+* ``recalculate_FIELD`` uses ``.update(cached_FIELD=`` to set the value.
+* ``flag_FIELD_as_stale`` uses ``.update``, as well.
TODO
----
View
@@ -1,3 +1,2 @@
[egg_info]
-tag_build = dev
-tag_svn_revision = true
+
View
@@ -1,13 +1,13 @@
from setuptools import setup, find_packages
import sys, os
-version = '0.1'
+version = '0.2'
setup(name='django-cached-field',
version=version,
- description="Cached fields on Django ORM for expensive-to-calculate data",
- long_description="""Cached fields on Django ORM for expensive-to-calculate data""",
+ description="Celery-deferred, cached fields on Django ORM for expensive-to-calculate data",
+ long_description="""Celery-deferred, cached fields on Django ORM for expensive-to-calculate data""",
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords='django caching',
author='Martin Chase',
@@ -18,7 +18,9 @@
include_package_data=True,
zip_safe=False,
install_requires=[
- # -*- Extra requirements: -*-
+ 'django>=1.3.1',
+ 'celery>=2.3.1',
+ 'django-celery>=2.3.3'
],
entry_points="""
# -*- Entry points: -*-

0 comments on commit 2f64f60

Please sign in to comment.