如果您正在实现 Django DirtyFields,在测试中使用固定装置时是否存在已知问题?
我们将django_nose
'sNoseTestSuiteRunner
用于固定装置和覆盖范围。我打算尝试实施django-dirtyfields
一些自定义post_save()
活动。我所做的唯一更改如下:
from dirtyfields import DirtyFieldsMixin
class BaseModel(DirtyFieldsMixin, models.Model):
"""
Base model
"""
class Meta:
abstract = True
我们使用它BaseModel
来扩展我们的大多数其他模型。添加DirtyFieldsMixin
导致我们的测试因以下重复错误而终止的原因:
Problem installing fixture '/home/ricomoss/workspace/project/settings/../apps/contracts/fixtures/test_contracts_data.json': Traceback (most recent call last):
File "/home/ricomoss/.virtualenvs/project/local/lib/python2.7/site-packages/django/core/management/commands/loaddata.py", line 193, in handle
for obj in objects:
File "/home/ricomoss/.virtualenvs/project/local/lib/python2.7/site-packages/django/core/serializers/json.py", line 47, in Deserializer
raise DeserializationError(e)
DeserializationError: Field matching query does not exist.
据我所知,每当夹具尝试加载时,都会发生此错误。有什么想法吗? DirtyFieldsMixin
不包括任何会导致我的灯具需要更新的新字段(更不用说必填字段了)。
编辑 1:看来我的问题与Django中的装置/信号问题直接相关。如果我们查看DirtyFieldsMixin
定义,我们可以立即看到问题所在(我已经验证了这一点):
class DirtyFieldsMixin(object):
def __init__(self, *args, **kwargs):
super(DirtyFieldsMixin, self).__init__(*args, **kwargs)
post_save.connect(
self._reset_state, sender=self.__class__,
dispatch_uid='{}-DirtyFieldsMixin-sweeper'.format(
self.__class__.__name__))
self._reset_state()
def _reset_state(self, *args, **kwargs):
self._original_state = self._as_dict()
def _as_dict(self):
return dict([(f.name, getattr(self, f.name)) for f in
self._meta.local_fields if not f.rel])
def get_dirty_fields(self):
new_state = self._as_dict()
return dict([(key, value) for key, value in
self._original_state.iteritems()
if value != new_state[key]])
def is_dirty(self):
# in order to be dirty we need to have been saved at least once, so we
# check for a primary key and we need our dirty fields to not be empty
if not self.pk:
return True
return {} != self.get_dirty_fields()
具体来说,
post_save.connect(self._reset_state, sender=self.__class__,
dispatch_uid='{}-DirtyFieldsMixin-sweeper'.format(
self.__class__.__name__))
我尝试根据给定的解决方案创建一个装饰器。我要么错误地实现了装饰器,要么在这种情况下不起作用。我对它在这种情况下的使用有点困惑。
我会把装饰器放在__init__
:
@utils.disable_for_loaddata
def __init__(self, *args, **kwargs):
super(DirtyFieldsMixin, self).__init__(*args, **kwargs)
post_save.connect(
self._reset_state, sender=self.__class__,
dispatch_uid='{}-DirtyFieldsMixin-sweeper'.format(
self.__class__.__name__))
self._reset_state()
在这种情况下,我仍然失败。有什么建议么?
编辑 2:我也尝试将装饰器添加到_reset_state
方法中。这也不起作用。
@utils.disable_for_loaddata
def _reset_state(self, *args, **kwargs):
self._original_state = self._as_dict()
编辑3:我认为我正在取得进展。我将inspect.stack()
装饰器的一部分__init__
直接移到了(就在post_save
调用上方)。
尽管我的测试套件仍未正确运行,但我正在进行其他活动。我不再收到 loaddata 错误。
def __init__(self, *args, **kwargs):
super(DirtyFieldsMixin, self).__init__(*args, **kwargs)
import inspect
for fr in inspect.stack():
if inspect.getmodulename(fr[1]) == 'loaddata':
return
post_save.connect(
self._reset_state, sender=self.__class__,
dispatch_uid='{}-DirtyFieldsMixin-sweeper'.format(
self.__class__.__name__))
self._reset_state()
编辑 4:我决定为此过程编写自己的 mixin。我不相信我需要为我的目的使用信号。因此,我将覆盖该save()
方法并以特殊方式处理它。