在 Django 1.3 中使用 ImageFields 测试模型时防止残留图像文件

发布于 2024-12-20 09:03:29 字数 250 浏览 2 评论 0 原文

Django 1.3 更改了带有 FileField 的模型的行为,以便在删除实例时保留实际文件。对于大多数用途来说,这很好。但是,我正在测试一个大量使用 ImageField 的应用程序,最终我的开发上传目录中出现了数百个无用的剩余图像。由于它是开发中的,所以这不是什么大问题,但我更愿意在测试后自行清理。

测试时让这些图像不徘徊的最佳方法是什么?我强调这一部分是因为我不想使用 delete 覆盖等全面修改此行为。

Django 1.3 changed the behavior of models with FileFields such that when the instance is deleted the actual file(s) remain. For most purposes, this is fine. However, I'm testing an application that makes heavy use of ImageFields and I'm ending up with hundreds of useless leftover images in my development upload directory. Since it's development, it's not a huge deal, but I'd prefer to clean up after myself in the tests.

What's the best way to make these images not hang around when testing. I emphasize that part because I don't want to modify this behavior across the board, using a delete override, etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

今天小雨转甜 2024-12-27 09:03:30

我崩溃了,妥协了一点。我决定继续使用覆盖的 delete,但我根据传递 include_images=True kwarg 来删除实际的图像文件。

class Photo(models.Model):
    ...
    def delete(self, *args, **kwargs):
        if kwargs.pop('include_images', False):
            for field in self._meta.fields:
                if type(field) == models.ImageField:
                    image = self.__getattribute__(field.name)
                    if image.name != '':
                        image.storage.delete(image.name)
        super(Photo, self).delete(*args, **kwargs)

然后,我在测试用例中修改了 tearDown 方法,如下所示:

def tearDown(self):
    for p in Photo.objects.all():
        p.delete(include_images=True)

我对这个解决方案并不完全满意,但它是我能得到的最接近我认为理想的解决方案。这实际上应该全部由测试本身来处理。

I broke down and compromised a bit. I decided to go ahead and use an overridden delete, but I made deleting the actual image files dependent on passing a include_images=True kwarg.

class Photo(models.Model):
    ...
    def delete(self, *args, **kwargs):
        if kwargs.pop('include_images', False):
            for field in self._meta.fields:
                if type(field) == models.ImageField:
                    image = self.__getattribute__(field.name)
                    if image.name != '':
                        image.storage.delete(image.name)
        super(Photo, self).delete(*args, **kwargs)

Then, I modified the tearDown method in my test cases like so:

def tearDown(self):
    for p in Photo.objects.all():
        p.delete(include_images=True)

I'm not entirely happy with this solution, but it's the closest I could get to what I consider ideal. This should really all be handled by the tests themselves.

一梦浮鱼 2024-12-27 09:03:30

调用 django cron 。 djangoproject.com/en/1.3/howto/custom-management-commands/" rel="nofollow">命令

A cron that call to django command

喜爱皱眉﹌ 2024-12-27 09:03:30

我遇到了这个问题,并在 Google 中找到了这篇文章。我更喜欢使用命令 - 所以这里有一些代码可能对其他人有用。这是在 Django 1.4 中,但应该适用于任何版本。我使用 WebTest

在基本测试类中:

def get_test_image_input(self):
    return (
        '_test-image.jpg',
        file(os.path.join(settings.TEST_FILES_PATH, "images", "test.jpg")).read()
    )

在任何测试中:

form['image'] = self.get_test_image_input()

为了事后清理,我只需删除命令中以 _test-image 开头的所有文件:

from django.core.management.base import BaseCommand
from fabric.operations import local

class Command(BaseCommand):

    def handle(self, *args, **options):
        # test an app call "tests"
        local("python manage_test.py test tests -v 2")
        # could use call_command(...) instead

        # remove all test images
        local("sudo rm -rf `find . -name _test-image*`")

I had the issue and found this post in Google. I much prefer to use a command instead - so here is some code which might be useful for others.That's in Django 1.4 but should work in any version. I use WebTest:

In the base test class:

def get_test_image_input(self):
    return (
        '_test-image.jpg',
        file(os.path.join(settings.TEST_FILES_PATH, "images", "test.jpg")).read()
    )

In any test:

form['image'] = self.get_test_image_input()

To clean up afterwards, I simply delete all files starting with _test-image in a command:

from django.core.management.base import BaseCommand
from fabric.operations import local

class Command(BaseCommand):

    def handle(self, *args, **options):
        # test an app call "tests"
        local("python manage_test.py test tests -v 2")
        # could use call_command(...) instead

        # remove all test images
        local("sudo rm -rf `find . -name _test-image*`")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文