#django #tdd #filtering
#django #tdd #фильтрация
Вопрос:
У меня есть приложение Django, которое хорошо работает для меня, но в настоящее время не имеет понятия о пользователе: я единственный, кто его использует, и я хотел бы это изменить…
За исключением представлений администратора, зарегистрированный пользователь не должен иметь доступа к данным, созданным другими пользователями. Между пользователями нет общих данных.
-
Я полагаю, мне нужно добавить
user
внешний ключ ко всем созданным мной моделям. Правильно? -
Есть ли простой способ реализовать фильтрацию на основе
request.user
? Можно ли это сделать более или менее автоматически, или мне нужно просмотреть весь код, чтобы проверить каждый запрос, выполняемый в базе данных? -
Я написал код с использованием TDD, и я намерен продолжить… Каковы наилучшие стратегии для обеспечения правильной реализации фильтрации пользователей, например, чтобы я не забыл отфильтровать существующий запрос? Я полагаю, я могу написать тесты, которые показывают, что конкретный запрос еще не отфильтрован, и реализовать фильтр. Но как насчет запросов, которые я напишу позже? Есть ли способ, которым я могу утверждать, что все существующие и будущие запросы возвращают объекты, которые принадлежат только текущему пользователю?
Спасибо.
Ответ №1:
Да, вам нужно будет добавить пользователя FK. Не забывайте, что вам придется перенести таблицы вашей базы данных — либо вручную, либо с помощью такого инструмента, как South.
Одним из способов реализации фильтра было бы определение пользовательских менеджеров для ваших моделей с for_user
методом, который принимает пользователя в качестве аргумента: что-то вроде:
class ForUserManager(models.Manager):
def for_user(self, user):
return self.filter(user=user)
Теперь вы можете использовать этот менеджер — с подклассами и / или с микшированием по мере необходимости — на всех ваших моделях и не забывайте использовать objects.for_user(request.user)
везде.
Это также упростит тестирование — ваш тест может использовать этот for_user
метод, чтобы он устанавливал флаг или счетчик где-нибудь в глобальной переменной, а затем проверял, что он увеличился, как ожидалось.
Редактировать в ответ на комментарий Нет, как вы подозреваете, это не сработает. Дело даже не в том, что все обязательно получат последнего вошедшего в систему пользователя: дело в том, что менеджеры являются атрибутами уровня класса и как таковые повторно используются на протяжении всего процесса, поэтому любой запрос, обслуживаемый этим серверным процессом, будет использовать один и тот же.
Комментарии:
1. Я могу представить следующее: когда пользователь входит в систему, я создаю экземпляр подкласса Manager, который (1) хранит
user
и (2) использует его для фильтрации набора запросов вget_query_set
. Затем я устанавливаю этот менеджер по умолчанию для своих моделей. Будет ли это работать с несколькими разными пользователями? Или все пользователи будут видеть объекты для последнего подключенного пользователя? Боюсь, последнее…