Ведение журнала аудита любых / всех объектов базы данных Python в GAE - PullRequest
1 голос
/ 15 июня 2011

Я новичок в Python. Я пытаюсь выяснить, как эмулировать существующее приложение, написанное мной с использованием PHP и MS-SQL, и заново создать базовую функциональность сервера в Google Apps Engine.

Одна из вещей, которые я пытаюсь сделать, - это эмулировать текущую активность в определенных таблицах, которые у меня есть в MS-SQL, а именно триггер вставки / удаления / обновления, который вставляет копию текущей записи (до изменения) в контрольную таблицу и ставит отметки с указанием даты и времени. Затем я могу запросить эту таблицу аудита позднее, чтобы изучить историю изменений, через которые прошла запись.

Я нашел следующий код здесь в stackoverflow:

class HistoryEventFieldLevel(db.Model):
    # parent, you don't have to define this
    date = db.DateProperty()
    model = db.StringProperty()
    property = db.StringProperty() # Name of changed property
    action = db.StringProperty( choices=(['insert', 'update', 'delete']) )
    old = db.StringProperty() # Old value for field, empty on insert
    new = db.StringProperty() # New value for field, empty on delete

Однако я не уверен, как этот код можно применить ко всем объектам в моей новой базе данных.

Должен ли я создавать функции get () и put () для каждого из моих объектов, а затем в функции put () я создаю дочерний объект этого класса и устанавливаю его конкретные свойства?

Ответы [ 2 ]

1 голос
/ 15 июня 2011

Это, конечно, возможно, хотя и несколько сложно. Вот несколько советов, с которых можно начать:

  • Переопределение метода класса put() недостаточно, поскольку сущности также можно сохранить, вызвав db.put(), что не вызовет никаких методов в классе, который пишется.
  • Вы можете обойти это, установив пакет SDK для вызова перехватчиков вызовов до / после, как описано в моем блоге здесь .
  • Кроме того, вы можете сделать это на более низком уровне, внедрив RPC-хуки, описанные в другом сообщении в блоге здесь .
  • Хранение записи аудита в качестве дочерней сущности модифицированной сущности является хорошей идеей и означает, что вы можете сделать это транзакционно, хотя это потребует дальнейших, более сложных изменений.
  • Вам не нужна запись для каждого поля. Объекты имеют естественный формат сериализации, буферы протокола, и вы можете просто сохранить объект в виде закодированного буфера протокола в записи аудита. Если вы работаете на уровне модели, используйте model_to_protobuf для преобразования модели в буфер протокола.
  • Все вышеперечисленное гораздо легче применить для хранения записи после ее изменения, чем до того, как она была изменена. Это не должно вызывать проблем - если вам нужна запись до того, как она была изменена, вы можете просто вернуться к одной записи в журнале аудита.
0 голосов
/ 15 июня 2011

Я немного потерял связь с GAE, и у меня нет sdk, чтобы протестировать его, поэтому вот несколько советов, чтобы дать вам подсказку, что вы можете сделать.

  1. Создайте метакласс AuditMetaкоторый вы устанавливаете в любых моделях, которые вы хотите проверять
  2. AuditMeta при создании нового класса модели должен копировать класс с новым именем с добавленным «_audit», а также должен также копировать атрибут, что становится немного сложнее в GAE в качестве атрибутовсами по себе являются дескрипторами
  3. Добавьте метод put к каждому такому классу и на месте создайте объект аудита для этого класса и сохраните его, чтобы для каждой строки в таблице A у вас была история в tableA_audit

например, простой пример Python (без GAE)

import new

class AuditedModel(object):
    def put(self):
        print "saving",self,self.date
        audit = self._audit_class()
        audit.date = self.date
        print "saving audit",audit,audit.date

class AuditMeta(type):
    def __new__(self, name, baseclasses, _dict):
        # create model class, dervied from AuditedModel
        klass = type.__new__(self, name, (AuditedModel,)+baseclasses, _dict)

        # create a audit class, copy of klass
        # we need to copy attributes properly instead of just passing like this
        auditKlass = new.classobj(name+"_audit", baseclasses, _dict)
        klass._audit_class = auditKlass

        return klass

class MyModel(object):
    __metaclass__ = AuditMeta

    date = "XXX"

# create object
a = MyModel()
a.put()

вывод:

saving <__main__.MyModel object at 0x957aaec> XXX
saving audit <__main__.MyModel_audit object at 0x957ab8c> XXX

Чтение контрольный журнал код, всего 200 строк, чтобы увидеть, какони делают это для Джанго

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...