我的基本目标是创建一个表单(使用ModelForm
)预先填充来自现有数据库对象的数据,允许用户修改这些数据,然后将提交的表单另存为 new 对象。 (排序为“复制”,然后“粘贴修改”设置。)除了文件字段和ClearableFileInput小部件之外,这种方式正常。
this,this和this等问题的答案清楚地表明,文件字段不能也不应该使用初始值填充。
然而,Django文档在ClearableFileInput窗口小部件上说:
文件上传输入:
<input type='file' ...>
,附加复选框输入以清除字段的值,如果该字段不是必需的且具有 初始 数据。< / p>
(有点令人困惑,但我认为Django指的是具有初始值的模型字段,而<input type='file' ...>
字段仍为空白?)
所以,如果我使用这种方法:
>>> obj = Foo.objects.get(pk=1)
>>> obj.fooFile.name
u'files/foo1.txt'
>>> f = FooForm(instance=obj)
或此方法:
f = FooForm(initial={'fooFile':Foo.objects.get(pk=1).fooFile})
要实例化我的表单,ClearableFileInput小部件显示:
Currently with clearing checkbox, Change... input http://phagesdb.org/static/formDisplay.png
但是,当用户提交表单而不更改此字段时,“当前”行中的值似乎完全丢失给Django。它似乎不在request.POST
或form.cleaned_data
中。当我在绑定的ModelForm上调用.is_valid()
然后.save()
时,文件字段在新对象中结束为空。
所以:
ClearableFileInput小部件是否会传递“当前”值?如果不是,ClearableFileInput小部件是否误导和/或使用非常有限?我假设返回的值将是“当前...”中的值,除非我使用“更改...”输入。
如何在我调用.save()
时捕获该值,使其显示在我的新对象中? (请记住,我不能使用f = FooForm(request.POST, request.FILES, instance=obj)
,因为我想要一个新对象,而不是一个修改过的对象。)
答案 0 :(得分:0)
在表单中放置一个隐藏字段,并使用您作为初始传入的图像的路径预填充它。然后编写一个类似以下的保存方法。
这对用户来说就好像文件字段已预先填充,将文件保存到新实例,并允许他们使用清除复选框,或上传他们自己的图像。
from django.core.files.base import ContentFile
def save(self, commit=True):
insance = super(FormClass, self).save(False)
if not instance.file_field and self.cleaned_data['file_field_path'] and not self.data.get('file_field-clear'):
path = os.path.join(settings.MEDIA_ROOT, self.cleaned_data['file_field_path'])
with open(path) as f:
file_object = ContentFile(f.read())
instance.file_field.save(self.cleaned_data['file_field_path'], file_object, False)
if commit:
insance.save()
return insance