【问题标题】:Django modelform custom widget is_multipart not workingDjango modelform自定义小部件is_multipart不起作用
【发布时间】:2020-10-07 01:24:23
【问题描述】:

在我的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 %}
...

【问题讨论】:

    标签: django django-forms django-views django-templates


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      这对我有用:

      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() 解决了这个问题

      【讨论】:

        猜你喜欢
        • 2020-03-20
        • 1970-01-01
        • 2019-12-16
        • 2018-05-25
        • 1970-01-01
        • 1970-01-01
        • 2012-04-10
        • 1970-01-01
        • 2014-10-05
        相关资源
        最近更新 更多