Зарегистрированные изменения в журнале аудита - PullRequest
1 голос
/ 23 апреля 2019

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

Код ниже работает, ноэто совсем не элегантно.Можете ли вы придумать более элегантный способ реализовать это?

def auditdiff(set1, set2):
    new = set(set1.items())
    old = set(session[set2].items())
    diffset = dict(old ^ new) # holds what has changed
    m = {}
    for d in diffset:
        for pair in old:
            if pair[0] == d:
                m[d + " OLD"] =  pair[1]

        for pair in new:
            if pair[0] == d:
                m[d + " NEW"] = pair[1]
    return(m)

Вот примеры переменных, перехваченных отладчиком:

set1: (старые значения)

<class 'dict'>: {'date': '2019-04-25', 'student_id': None, 'booking_id': '', 'key': '', 'status': 'ATTEND', 'note': 'this is a changed note', 'charge': False}

set2: (новые значения)

<class 'set'>: {('date', '2019-04-25'), ('note', 'this is a note'), ('student_id', None), ('charge', False), ('key', ''), ('status', 'ATTEND'), ('booking_id', '')}

diffset: (разница)

<class 'dict'>: {'note': 'this is a changed note'}

m: (старые и новые измененные значения)

<class 'dict'>: {'note OLD': 'this is a note', 'note NEW': 'this is a changed note'}

С уважением

Джеймс

Ответы [ 3 ]

2 голосов
/ 23 апреля 2019

Как насчет этого?auditdiff здесь принимает два словаря и генерирует 4 кортежа, описывающих изменения:

  • первое значение - это затронутый ключ
  • второе значение - глагол added / removed/ changed
  • третье значение - старое значение, если оно есть
  • четвертое значение - новое значение, если оно есть

Изменения всегда выдаютсяв порядке лексикографического ключа.

def auditdiff(d1, d2):
    for key in sorted(set(d1) | set(d2)):
        if key in d1 and key not in d2:
            yield (key, "removed", d1[key], None)
        elif key in d2 and key not in d1:
            yield (key, "added", None, d2[key])
        elif d1[key] != d2[key]:
            yield (key, "changed", d1[key], d2[key])


d1 = {
    "date": "2019-04-25",
    "student_id": None,
    "booking_id": "",
    "key": "",
    "status": "ATTEND",
    "note": "this is a changed note",
    "charge": False,
    "greeting": "hello",  # this was added c.f. the original demo data
}
d2 = {
    "charge": False,
    "note": "this is a note",
    "key": "",
    "date": "2019-04-25",
    "student_id": None,
    "status": "ATTEND",
    "booking_id": "",
    "hello": "world",  # this was added c.f. the original demo data
}


for difference in auditdiff(d1, d2):
    print(difference)

выходные данные

('greeting', 'removed', 'hello', None)
('hello', 'added', None, 'world')
('note', 'changed', 'this is a changed note', 'this is a note')
0 голосов
/ 23 апреля 2019

Вот решение, основанное на вашем. Предполагается, что оба словаря имеют одинаковые ключи.

d1 = {
    "date": "2019-04-25",
    "student_id": None,
    "booking_id": "",
    "key": "",
    "status": "ATTEND",
    "note": "this is a changed note",
    "charge": False,
}
d2 = {
    "charge": False,
    "note": "this is a note",
    "key": "",
    "date": "2019-04-25",
    "student_id": None,
    "status": "ATTEND",
    "booking_id": "",
}

diffset = dict(set(d1.items()) ^ set(d2.items()))  # holds what has changed

m = {}
for key in diffset:
    m[key + " OLD"] = d1[key]
    m[key + " NEW"] = d2[key]

print(m)
0 голосов
/ 23 апреля 2019

Несколько причудливое решение:

d1 = {
    "date": "2019-04-25",
    "student_id": None,
    "booking_id": "",
    "key": "",
    "status": "ATTEND",
    "note": "this is a changed note",
    "charge": False,
    "greeting": "hello",  # this was added c.f. the original demo data
}
d2 = {
    "charge": False,
    "note": "this is a note",
    "key": "",
    "date": "2019-04-25",
    "student_id": None,
    "status": "ATTEND",
    "booking_id": "",
    "hello": "world",  # this was added c.f. the original demo data
}

class LabeledTuple(tuple):
    def __new__(cls, t, label):
        result = super().__new__(cls, t)
        result.label = label
        return result

    def __repr__(self):
        return self.label + super().__repr__()


def labeled_set(d, name):
    return {LabeledTuple(t, name) for t in d.items()}


print(sorted(labeled_set(d1, "OLD") ^ labeled_set(d2, "NEW")))
# [OLD('greeting', 'hello'), NEW('hello', 'world'), OLD('note', 'this is a changed note'), NEW('note', 'this is a note')]

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