我有一个小项目,正在进行一些测试。最近我问了一个问题:django-test-mocked-imagefield-防止-上传-或-测试后清理 https://stackoverflow.com/questions/42266305/django-test-mocked-imagefield-prevent-upload-or-clean-after-test。我在模拟存储方面取得了一些进展,但目前我遇到了在 save() 方法中使用 update() 模拟模型存储的问题。
现在的情况:
<..crop..>
import mock
current_storage = 'django.core.files.storage.default_storage._wrapped'
def _mock_storage():
return mock.MagicMock(spec=Storage, name="StorageMock")
class ProjectsTest(TestCase):
fixtures = ['projects']
@mock.patch(current_storage, _mock_storage())
def _create_project(self, name):
return Project.objects.create(
name=name,
short_description="Short description A",
full_description="Full description A",
url="http://test-project-url.com/",
is_published=True)
@mock.patch(current_storage, _mock_storage())
def _create_project_image(self, project, name):
return ProjectImage.objects.create(
project=project,
name=name,
description="Description",
image=self._create_mock_image(name="Mocked Image"),
is_primary=True,
is_published=True)
创建一个新对象_create_project()
工作正常。在中创建一个新对象_create_project_image()
向我抛出一个错误(帖子底部的堆栈跟踪):
ValueError: Failed to insert expression "<MagicMock name='StorageMock.save().width.resolve_expression()' id='140674024419280'>" on projects.ProjectImage.image_width. F() expressions can only be used to update, not to insert.
这是因为我在模型的保存中有一个 update() (某些字段
被删除,因为它们对问题不感兴趣):
class ProjectImage(models.Model):
project = models.ForeignKey(
'projects.Project')
name = models.CharField(
_("Image name"),
max_length=35)
image = models.ImageField(
_("Project image"),
upload_to=project_image_upload_location,
width_field='image_width',
height_field='image_height')
image_width = models.IntegerField(
default=0)
image_height = models.IntegerField(
default=0)
is_primary = models.BooleanField(
_("Primary project image?"),
default=False)
def save(self, *args, **kwargs):
self.update_primary_project_image()
return super(ProjectImage, self).save(*args, **kwargs)
def update_primary_project_image(self):
if self.is_primary:
self.__class__.objects \
.filter(project=self.project, is_primary=True) \
.update(is_primary=False)
堆栈跟踪:
Creating test database for alias 'default'...
.......E.
======================================================================
ERROR: test_unset_current_primary_image_on_save (projects.tests.ProjectsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/edwin/git/portofolio/apps/projects/tests.py", line 105, in test_unset_current_primary_image_on_save
self._create_project_image(project=project, name="Image A2")
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/home/edwin/git/portofolio/apps/projects/tests.py", line 42, in _create_project_image
is_published=True)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/query.py", line 399, in create
obj.save(force_insert=True, using=self.db)
File "/home/edwin/git/portofolio/apps/projects/models.py", line 91, in save
return super(ProjectImage, self).save(*args, **kwargs)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/base.py", line 824, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/base.py", line 908, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/base.py", line 947, in _do_insert
using=using, raw=raw)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/query.py", line 1045, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1053, in execute_sql
for sql, params in self.as_sql():
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1006, in as_sql
for obj in self.query.objs
File "/home/edwin/.virtualenvs/portofolio/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 940, in prepare_value
'can only be used to update, not to insert.' % (value, field)
ValueError: Failed to insert expression "<MagicMock name='StorageMock.save().width.resolve_expression()' id='139904200277904'>" on projects.ProjectImage.image_width. F() expressions can only be used to update, not to insert.
----------------------------------------------------------------------
Ran 9 tests in 0.123s
问题:如何使用模拟存储正确测试模型中的更新?或者我试图在这里做一些完全不可能的事情?
任何建议、解释或推动解决此问题的正确方向将不胜感激。谢谢。