Эти проблемы легко можно решить использую ленивые запросы к базе данных. И рискуя таки нарваться на изобретение велосипеда, я всё таки написал небольшой модуль lazydb, для ленивого доступа к БД через джанговский ORM:
# Wrappers for lazy database access
class LazySingleton:
_singelton = None
def __init__(self, singelton_class):
self._singelton_class = singelton_class
def __getattr__(self, name):
if not self._singelton:
self._singelton = self._singelton_class.get_instance()
return getattr(self._singelton, name)
class LazyFirst:
_obj = None
def __init__(self, query_set):
self._query_set = query_set
def __getattr__(self, name):
if not self._obj:
self._obj = self._query_set[0]
return getattr(self._obj, name)
class LazyCount:
def __init__(self, query_set):
self._query_set = query_set
def __int__(self):
if not hasattr(self, '_count'):
self._count = self._query_set.count()
return self._count
def __str__(self):
return str(self.__int__())
def __unicode__(self):
return unicode(self.__str__())
LazySingleton - это ленивый запрос на получение экземляра, класс которого определяет метод get_instance. Я использую его для получения объекта настроек (Preferences), таблица содержит тольку одну запись. И в большинстве случаев этот объект будет необходим только на страницах этого приложения. И возможность делать показанный ниже запрос из шаблонов, не задумыватясь о передаче нужного объекта представляется довольно удобной.
{{ pref.forum.posts_on_page }}
LazyFirst и LazyCount вытаскивают соответсвенно первый объект и число объектов из переданных в качестве параметров QuerySet'ов.
Стоит заметить, что эти ленивые запросы не только ленивые, но ещё и кэширующие, причём кэширующие безусловно. Таким образом запрос к базе будет выполняться только один раз и только если это понадобиться. Вероятно это не везде будет тем, что нужно, поэтому нужно иметь это в виду.
Пока только эти простые запросы, другие мне не были ещё нужны, но по аналогии всегда можно добавить дополнительные. Хотя можно повозиться и придумать что-то более универсальное. Например, строку питон кода, который будет выполняться посредством exec, функцию, и вообще что-угодно.
Я это использую при сборе статистики из приложений, которые возвращают словарь функцией get_statistics.
Сбор общей статистики в ядре cms:
def get_statistics():
stat = {}
stat['user_number'] = LazyCount(User.objects)
stat['last_user'] = LazyFirst(User.objects.order_by('-date_joined'))
return stat
Сбор статистики форума:
def get_statistics():
stat = {}
stat['post_number'] = LazyCount(Post.objects)
stat['topic_number'] = LazyCount(Topic.objects)
stat['forum_number'] = LazyCount(Forum.objects)
return stat
При большом кол-ве данных, которые могут и не потребоваться, этот подход может серьёзно сократить нагрузку на СУБД. Хотя это ещё нужно протестировать, ведь создание объектов обёрток тоже не совсем бесплатно.

Комментариев нет:
Отправить комментарий