Безопасный по умолчанию уровень Django ORM --- как?

Я управляю магазином Django, где мы обслуживаем каждого нашего клиента графом объектов, который полностью отделен от графов всех других клиентов. Данные являются умеренно чувствительными, поэтому я не хочу, чтобы какая-либо из них передавалась от одного клиента другому, а также чтобы один клиент не удалял или не изменял данные другого клиента.

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

Мой главный страх в том, что в Twig.objects.get(...)Забываю добавить client=request.clientи аналогично для Leaf.objects.get где я должен проверить это twig__client=request.client, Это быстро становится подверженным ошибкам и сложным.

Какие есть хорошие способы обойти мою забывчивость? Как сделать из этого то, о чем мне не нужно думать?

2 ответа

Я объясню другую проблему, которая у меня была, однако я думаю, что решение может быть чем-то, на что стоит обратить внимание

Однажды я работал над проектом по визуализации данных, где мне нужно было иметь действительно большую таблицу, в которой будут храниться все данные для всех визуализаций. Это оказалось большой проблемой, потому что мне пришлось бы делать такие вещи, как Model.objects.filter(visualization=5) который был просто не очень элегантным и не эффективным.

Чтобы сделать вещи проще и эффективнее, я создал динамические модели на лету. По сути, я бы создал отдельную таблицу в БД на лету, а затем сохранял бы данные только для этой одной визуализации. Мой код что-то вроде:

def get_model_class(table_name):
    class ModelBase(ModelBase):
        def __new__(cls, name, bases, attrs):
            name = '{}_{}'.format(name, table_name)
            return super(ModelBase, cls).__new__(cls, name, bases, attrs)


    class Data(models.Model):
        # fields here
        __metaclass__ = ModelBase
        class Meta(object):
            db_table = table_name

    return Data

dynamic_model = get_model_class('foo')

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

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

Одно из возможных решений, которое я имею в виду:

  • Установите менеджер объектов по умолчанию как DANGER = models.Manager() на мой абстрактный базовый класс (ы).
  • Есть метод ok(request) на указанных базовых классах, который применяется .filter(leaf__twig__branch__trunk__root__client=request.client) применимо.
  • использование MyModel.ok(request) вместо MyModel.objects везде, где это возможно.

Можно ли это улучшить? Одна не очень хорошая проблема - когда представление вызывает метод модели, например branch.get_twigs_with_fruitТеперь я должен пройти request чтобы он пробежал ok или я должен призвать DANGER, Мне не нравится ни

Есть ли способ получить доступ к текущему запросу? Я думаю, что это может смягчить ситуацию...

Другие вопросы по тегам