Параметризация фильтра запросов в наборе менеджеров в Django - PullRequest
0 голосов
/ 20 февраля 2019

Я хочу реализовать защиту на уровне строк для моей модели в Django.Я хочу отфильтровать данные настолько низко, насколько это возможно, исходя из некоторых требований.

Теперь я знаю, что мог бы создать определенные менеджеры для этой модели, как говорит docs , но мне кажется, что он должен быть статическим.Я также знаю, что могу создать только метод, который будет возвращать набор запросов, как я хочу, но мне будет недостаточно, я имею в виду, что возможность просто получить все данные еще есть, и самая простая ошибка может привести к их утечке.

Итак, я нашел этот пост, но, как сказал автор, небезопасно и не очень приятно возиться с глобальными государствами.Этому посту уже почти 10 лет, поэтому я надеюсь, что, возможно, кто-то придумал лучшее универсальное решение.

Вот пример для наглядного представления того, что мне нужно:

models.py:

class A(models.Model): 
    ...

class B(models.Model): 
    user = models.ForeignKey(User) 
    a = models.ForeignKey(A)

И я хочу создать глобальную функциональность для получения объектов A только в том случае, если существует экземпляр B с user как зарегистрированный пользователь.

Я пришел к решению простопереопределить get_queryset() из A менеджера, например, так:

Manager.py

class AManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset(b__user=**and_here_i_need_a_user**)

, но я не могу найти параметры для его параметризации.

==== РЕДАКТИРОВАТЬ ====

Другая идея состоит в том, чтобы просто не позволять получать наборы запросов A явно, но только через связанное поле из B, но я не могу найти ссылки, как это сделать.Кто-нибудь делал что-то подобное?

1 Ответ

0 голосов
/ 20 февраля 2019

Так что вы как будто на правильном пути.Как насчет чего-то вроде этого ...

class AQuerySet(models.QuerySet):
    def filter_by_user(self, user, *args, **kwargs):
        user_filter = Q(b__user=user)
        return self.filter(user_filter, *args, **kwargs)

class AManager(models.Manager):
    queryset_class = AQuerySet

    def filter_by_user(self, user, *args, **kwargs):
        return self.get_queryset().filter_by_user(user, *args, **kwargs)

class A(models.Model):
    objects = AManager()
    # ...

, тогда вы можете использовать это так:

A.objects.filter_by_user(get_current_user(), some_filter='some_value')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...