Написан пользовательский логгер, он используется при редактировании или модификации объектов. Появилось поле с отношением «многие ко многим», и его изменение не отображается. Как это можно исправить?
Код обработчика:
class BaseLog(metaclass=ABCMeta):
def __init__(self, instance, created):
self.diff = {}
self.created = created
self.new_instance = instance
self.old_instance = self._get_object(instance.id)
self.fields = self._get_fields()
def update_diff(self, field, new, old=None):
print(old)
if old is None:
self.diff[field] = new
else:
if old != new:
self.diff[field] = (old, new)
def get_diff(self):
for field in self.fields:
if self.old_instance is not None:
self.update_diff(
field[0],
getattr(self.new_instance, field[1]),
getattr(self.old_instance, field[1]),
)
else:
self.update_diff(field[0], getattr(self.new_instance, field[1]))
return self.diff
@abstractmethod
def _get_object(self, obj_id):
pass
@abstractmethod
def _get_fields(self):
pass
Код для моей модели:
class ServiceLog(BaseLog):
def _get_object(self, obj_id):
if self.created:
return None
try:
return Service.objects.get(id=obj_id)
except Service.DoesNotExist:
return None
def _get_fields(self):
return [
('flow', 'flow_name'),
('currency', 'currency_iso_name'),
('contractor', 'contractor_name'),
('amount', 'amount'),
('callback_url', 'callback_url'),
('definition', 'definition'),
('description', 'description'),
('charge_strategy', 'charge_strategy'),
('routine', 'routine'),
('service_keys', 'service_keys')
]
Сохранить запись:
@receiver([pre_save_with_user, post_save_with_user])
def logger_update_callback(sender, **kwargs):
is_created = kwargs['created']
if sender == Service:
obj_log = ServiceLog(kwargs['instance'], is_created)
elif sender == Deal:
obj_log = DealLog(kwargs['instance'], is_created)
else:
raise NotImplementedError(
'Logs for the model {} are not implemented'.format(sender)
)
log_record = {'who': str(kwargs.get('user', None)), 'what_model': sender.__name__,
'what_str': str(kwargs['instance']), 'what_id': kwargs['instance'].id, 'is_created': is_created,
'diff': obj_log.get_diff()}
if log_record['diff']:
log = Log.objects.create(**log_record)
log.save()
else:
pass
Model.py:
class Service(models.Model):
flow = models.ForeignKey(
Flow,
on_delete=models.CASCADE,
related_name='services_flows'
)
currency = models.ForeignKey(
Currency,
on_delete=models.CASCADE,
related_name='services_currencies'
)
contractor = models.ForeignKey(
Contractor,
on_delete=models.CASCADE,
related_name='services_contractors',
)
amount = models.IntegerField(default=0)
callback_url = models.CharField(
max_length=128,
blank=True,
null=True,
default=None,
)
definition = JSONField(null=True, blank=True, default=dict())
name = models.CharField(max_length=255, db_index=True)
description = models.TextField(null=True, blank=True)
charge_strategy = models.CharField(max_length=64, default='default')
routine = JSONField(null=True, blank=True, default=dict())
service_keys = models.ManyToManyField(ApiKey, through='ServiceKey')
@property
def currency_iso_name(self):
return str(self.currency)
@property
def contractor_name(self):
return str(self.contractor)
@property
def flow_name(self):
return str(self.flow)
@signal_sending(pre_save_with_user, post_save_with_user)
def save(self, *args, **kwargs):
super(Service, self).save(*args, **kwargs)
def __str__(self):
return '{}'.format(self.name)
def __repr__(self):
return self.name
Промежуточная таблица:
class ServiceKey(models.Model):
service = models.ForeignKey(
Service,
on_delete=models.CASCADE,
related_name='service',
null=False,
primary_key=True
)
key = models.ForeignKey(
ApiKey,
on_delete=models.CASCADE,
related_name='apikey',
null=False
)
class Meta:
unique_together = (('service', 'key'),)
Корректная работа:
Снимок экрана с отображением нового объекта
Когда я взаимодействую только с полем servicekey
:
Снимок экрана с некорректной работой
UPD: Я нашел информацию о m2m_change
, но не могу отправить сигнал.
Мой код:
@receiver(m2m_changed, sender=Service.service_keys.through)
def logger_callback2(sender, **kwargs):
print('M2MSIGNAL')