Безопасный по умолчанию уровень 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
, Мне не нравится ни
Есть ли способ получить доступ к текущему запросу? Я думаю, что это может смягчить ситуацию...