Django模型窗体自定义小部件is_multipart不工作



在我的modelform中,我使用了一个自定义小部件。问题是由于某种原因,is_multipart返回False,因此我无法上传图片

class ProjectSetupForm(ModelForm):

class Meta:
model = Project
fields = ['name', 'logo','picture']
widgets = {
'picture': PictureWidget,
'logo': PictureWidget,
}     
def __init__(self, *args, **kwargs):
self.fields['logo'].widget.attrs['class'] = 'file_upload blocked'
self.fields['picture'].widget.attrs['class'] = 'file_upload blocked'
class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None, **kwargs):
if value:
html =  Template("""<img src="$media$link" height=100px width=auto/>
<input type="file" name="$name" class=" form-control" style="width: 100%; height: auto" />""")
return mark_safe(html.substitute(media=settings.MEDIA_URL, link=value, name=name))
else:
html =  Template("""<input type="file" name="$name" class=" form-control" style="width: 100%; height: auto" />""")
return mark_safe(html.substitute(name=name))

# views.py:
class AddProject(View):
template_name   = 'project.html'
model           = Project

def get(self, request, *args, **kwargs):
...
context['form']   = ProjectSetupForm()
...
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
...
project_form   = ProjectSetupForm(request.POST if any(request.POST) else None, request.FILES or None)
if project_form.is_valid() and address_form.is_valid():
...
address_instance = address_form.save()
project_instance = project_form.save(commit = False)
project_instance.address = address_instance
project_instance.save()
else:
errors = {}
if project_form.errors:
project_form_errors = project_form.errors
errors.update( {'project_form': project_form_errors} )
if address_form.errors:
address_form_errors = address_form.errors
errors.update( {'address_form': address_form_errors} )

context = {}
context['errors'] = errors

return render(request, self.template_name, context)
# In template:
{% if form.is_multipart %}    
<form action="" method='POST' enctype="multipart/form-data" class="test" autocomplete = "on">
{% else %}
<form action="" method='POST' class="test" autocomplete = "on">
{% endif %}
{% csrf_token %}
...

当您添加一个通过文本操作呈现文件输入的Widget时,您假设它神奇地变成了true。这需要姜戈进行一些非常脆弱的反省。相反,它有一个你的Widget不使用的非常简单的界面:

# django.forms.widgets.Widget
class Widget(metaclass=MediaDefiningClass):
needs_multipart_form = False  # Determines does this widget need multipart form

以下是对我有效的方法:

class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None, **kwargs):
if value:
html =  Template("""<img src="$media$link" height=100px width=auto/>
<input type="file" name="$name" class=" form-control" style="width: 100%; height: auto" />""")
return mark_safe(html.substitute(media=settings.MEDIA_URL, link=value, name=name))
else:
html =  Template("""<input type="file" name="$name" class=" form-control" style="width: 100%; height: auto" />""")
return mark_safe(html.substitute(name=name))
class ProjectSetupForm(ModelForm):
class Meta:
model = Project
fields = ['name', 'logo','picture']

def __init__(self, *args, **kwargs):
self.fields['logo'].widget.attrs['class'] = 'file_upload blocked'
self.fields['picture'].widget.attrs['class'] = 'file_upload blocked'
...
self.fields['logo'].widget = PictureWidget()
self.fields['picture'].widget = PictureWidget()

问题似乎是从未调用过小部件。因此,self.fields['logo'].widget = PictureWidget()解决了问题

最新更新