Можно ли в django применить фильтр менеджера на основе переменной?
Мы хотели бы применить определенный фильтр в приложении django как способ предотвратить случайную утечку данных (и потребовать от разработчиков явного выражения намерений).
Допустим, у нас есть модель Project и модель Book, и мы хотим предотвратить Book.objects.all()
без фильтрации на проекте.
Я бы хотел что-то вроде этого:
Book.objects.for_project(project) -> Should return a QuerySet with all books for a specific project
Book.objects.all_projects() -> Should return a QuerySet with all books, i.e. for usage in data migration commands
Book.objects.all_projects().filter() -> Should be chainable
Book.objects.all() -> Should throw a DataLeakError()
Book.objects.filter() -> Should throw a DataLeakError()
Book.objects.exclude() -> Should throw a DataLeakError()
Book.objects.only() -> Should throw a DataLeakError()
....etc
Существует ли стандартный шаблон для чего-то подобного, или это антишаблон?
Интересный вопрос! Вы, конечно, можете написать метод custom manager для создания методов типа all_projects()
и поднимать ошибки для данного метода.
class Book(models.Model):
objects = BookManager()
ИЛИ вы можете предоставить вторичный менеджер объектов, например
class Book(models.Model):
permission_objects = BookManager()
Что все равно позволит вам получить все данные через ORM, если возникнет необходимость избежать этого набора фильтров.
class BookManager(models.Manager):
def for_project(proj):
return self.filter(project=proj)
Существует ли стандартный шаблон для чего-то подобного, или это антишаблон?
Я думаю, что это зависит от вашего приложения. Использование пользовательских методов менеджера, конечно, не является анти-паттерном. В Django Rest Framework- это обычно обрабатывается явно в permissions
слое (который вполне может использовать пользовательские методы менеджера!). Однако если вы имеете дело со стандартными представлениями, я думаю, что это допустимо.
Согласен. Выбрасывание ошибок на такие вещи как .all()
может вызвать головную боль, которую придется обходить при работе с некоторыми встроенными модулями, ярлыками и плагинами, если вы используете общие вещи, такие как ViewSets, например.