How To Avoid Import-time Database Access In Django?
Solution 1:
I've run into the same issue myself, and agree that it would be great to have some best practices here.
I ended up with an approach based on the descriptor protocol:
classLazyInstance:
def__init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.instance = Nonedef__get__(self, obj, cls):
if self.instance isNone:
self.instance, _ = cls.objects.get_or_create(*self.args, **self.kwargs)
return self.instance
Then in my model classes I have some special objects:
classCategory(models.Model):
name = models.CharField()
DOGS = LazyInstance(name="dogs")
CATS = LazyInstance(name="cats")
So nothing happens at import time. The first time the special object is accessed, the relevant instance is looked up (and created, if necessary) and cached.
Solution 2:
There's not much you can do with module-level variables, since you cannot override their access functions. However you can do that for class and instance variables via __getattribute__
. You can use that to load your categories lazily:
classCategories(object):
_categories = {'DOGS': 'dogs', 'CATS': 'cats'}
def__getattribute__(self, key):
try:
returnsuper(Categories, self).__getattribute__(key)
except AttributeError:
passtry:
value = load_category(self._categories[key])
except KeyError:
raise AttributeError(key)
setattr(self, key, value)
return value
Categories = Categories() # Shadow class with singleton instance
Instead of module.DOGS
you would then use module.Categories.DOGS
. Upon the first access the category is loaded and stored for future lookups.
Solution 3:
I've used lazy_object_proxy (wich works with passed function but without passed arguments) in companion with functools.partial like below:
import lazy_object_proxy
from functools import partial
defload_category(name):
# prepare an argument-less runnable function
loader = partial(Category.objects.get, name)
# pass the function to the proxyreturn lazy_object_proxy.Proxy(loader)
DOGS = load_category("dogs")
CATS = load_category("cats")
Post a Comment for "How To Avoid Import-time Database Access In Django?"