Фильтр django-запроса, установленный операцией без базы данных
Работа с ReviewBoard 1.6.11, в которой используется Django 1.3.3. Существует класс RepositoryManager, у которого есть метод с именем "available", определяемый так:
class RepositoryManager(Manager):
def accessible(self, user, visible_only=True, local_site=None):
"""Returns repositories that are accessible by the given user."""
if user.is_superuser:
qs = self.all()
else:
q = Q(public=True)
if visible_only:
q = q & Q(visible=True)
if user.is_authenticated():
q = q | (Q(users__pk=user.pk) |
Q(review_groups__users=user.pk))
qs = self.filter(q).distinct()
return qs.filter(local_site=local_site)
Проблема в том, что я хочу отфильтровать результаты этого запроса чем-то еще, что не взаимодействует с базой данных (разрешения файловой системы пользователя). Функция available() должна возвращать QuerySet. В противном случае я бы просто создал список и заполнил его соответствующими элементами из результата.
Я довольно новичок в Джанго. Это разумно, или я все делаю неправильно?
1 ответ
Я смог решить эту проблему, создав подкласс QuerySet следующим образом:
class RepositoryQuerySet(QuerySet):
def __init__(self, *args, **kwargs):
super(RepositoryQuerySet, self).__init__(*args, **kwargs)
self._user_filter = None
def _clone(self, *args, **kwargs):
retval = super(RepositoryQuerySet, self)._clone(*args, **kwargs)
retval._user_filter = self._user_filter
return retval
def filter_by_user_access(self, user):
self._user_filter = user.username
def iterator(self):
for repo in super(RepositoryQuerySet, self).iterator():
if self._user_filter is None:
yield repo
continue
# ...logic for restricting access by user...
# If user has access, just yield repo. If not, just 'continue'
Затем в RepositoryManager.accessible, сразу после вызова методика Different(), вызовите:
qs.filter_by_user_access(user)
Наконец, чтобы менеджер использовал новый класс набора запросов, создайте:
def get_query_set(self):
return RepositoryQuerySet(self.model, using=self.db)
в классе RepositoryManager.