Django中图片删除与更新的单元测试及InlineFormset参数疑问
Django InlineFormset 图片更新/删除单元测试:所需参数详解
你已经基于inlineformset_factory创建了关联Lodging和ImageModel的表单集,现在要写单元测试验证图片的更新和删除功能,核心是要给表单集传递正确的关联实例、POST数据(含表单集管理参数),以及更新时的文件对象。下面分场景详细说明:
一、更新图片的测试参数
更新图片时,表单集需要三个核心参数:
instance=lodging:必须指定关联的Lodging实例,告诉表单集要操作哪个房源下的图片data:遵循Django inline formset的命名规则构造POST数据,必须包含以下管理字段和图片字段:imagemodel_set-TOTAL_FORMS:表单集中的总表单数量(对应现有图片的数量)imagemodel_set-INITIAL_FORMS:初始已存在的表单数量(和总表单数一致,因为我们是更新现有图片)imagemodel_set-<index>-id:要更新的ImageModel实例ID,必须传,否则表单集无法识别要修改哪张图
files:如果要替换图片,需要传递模拟的上传文件对象,键名和data里的图片字段对应
举个实际的测试代码例子:
from django.test import TestCase from django.core.files.uploadedfile import SimpleUploadedFile from .models import Lodging, ImageModel from .forms import ImageFormset class ImageFormsetTests(TestCase): def setUp(self): # 初始化测试数据 self.lodging = Lodging.objects.create(name="山间小屋") self.test_image = ImageModel.objects.create( lodging=self.lodging, image=SimpleUploadedFile("旧图.jpg", b"模拟图片内容", content_type="image/jpeg") ) def test_update_existing_image(self): # 准备新的测试图片 new_test_image = SimpleUploadedFile("新图.jpg", b"新的模拟图片内容", content_type="image/jpeg") # 构造POST数据 form_data = { 'imagemodel_set-TOTAL_FORMS': '1', 'imagemodel_set-INITIAL_FORMS': '1', 'imagemodel_set-MAX_NUM_FORMS': '1', 'imagemodel_set-0-id': str(self.test_image.id), } # 构造文件数据 file_data = { 'imagemodel_set-0-image': new_test_image } # 初始化表单集,传入所有必要参数 formset = ImageFormset(instance=self.lodging, data=form_data, files=file_data) # 验证并保存 self.assertTrue(formset.is_valid()) formset.save() # 断言图片已更新 updated_image = ImageModel.objects.get(id=self.test_image.id) self.assertIn("新图.jpg", updated_image.image.name)
二、删除图片的测试参数
删除图片的核心是触发表单集的DELETE标记,需要传递的参数:
instance=lodging:同样必须指定关联的Lodging实例data:除了管理字段(总表单数、初始表单数),还要给要删除的图片表单加上DELETE字段,值设为on或True,同时必须包含该图片的id字段
测试代码示例:
def test_delete_existing_image(self): # 构造包含DELETE标记的POST数据 form_data = { 'imagemodel_set-TOTAL_FORMS': '1', 'imagemodel_set-INITIAL_FORMS': '1', 'imagemodel_set-MAX_NUM_FORMS': '1', 'imagemodel_set-0-id': str(self.test_image.id), 'imagemodel_set-0-DELETE': 'on', # 标记该图片需要删除 } # 初始化表单集,传入instance和data formset = ImageFormset(instance=self.lodging, data=form_data) # 验证并保存 self.assertTrue(formset.is_valid()) formset.save() # 断言图片已被删除 self.assertEqual(ImageModel.objects.count(), 0)
额外注意事项
- 表单前缀:如果创建
ImageFormset时指定了prefix参数(比如inlineformset_factory(..., prefix='room_images')),那所有data里的键都要改成room_images-<index>-字段名的格式 - 多图片场景:如果有多个图片,
TOTAL_FORMS要设为实际图片数量,每个图片对应一个索引(0、1、2...),要删除哪张就给对应的索引加DELETE字段即可 - 文件模拟:单元测试里一定要用
SimpleUploadedFile模拟上传文件,不要依赖真实文件路径,保证测试的独立性和可重复性
内容的提问来源于stack exchange,提问作者s.singh
相关产品推荐
相关产品推荐

