Django DirtyFields を実装している場合、テストでフィクスチャを使用する際に既知の問題はありますか?
フィクスチャとカバレッジでを使用しdjango_nose
ます。いくつかのカスタムアクティビティを実行するNoseTestSuiteRunner
ために実装しようとしていました。私が行った唯一の変更は次のとおりです。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()
この場合、まだ失敗します。助言がありますか?
EDIT 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()
これを特別な方法で処理します。