Можно ли в 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, например.

Вернуться на верх