彩云之南雪域之巅 2023-12-03 19:39 采纳率: 50%
浏览 27
已结题

ValueError: ClearableFileInput doesn't support uploading multiple files

问题遇到的现象和发生背景

Django 使用form实现多文件上传,是《Django3Web应用开发实践》(黄永祥著)这本书 第8章 表单与模型 8.9 多文件批量上传的示例,但运行出错,进行数据迁移时报错!

遇到的现象和发生背景,请写出第一个错误信息

ValueError: ClearableFileInput doesn't support uploading multiple files.

用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
from django import forms
from .models import *

class PersonInfoForm(forms.ModelForm):
    certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': True}))
    class Meta:
        model = PersonInfo
        fields = '__all__'
        labels = {
            'name': '名字',
            'age': '年龄',
        }
运行结果及详细报错内容
tactics@qbpb:/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango$ python manage.py makemigrations
/usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (2.1.0) or chardet (3.0.4) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.8/dist-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.8/dist-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.8/dist-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.8/dist-packages/django/core/management/base.py", line 453, in execute
    self.check()
  File "/usr/local/lib/python3.8/dist-packages/django/core/management/base.py", line 485, in check
    all_issues = checks.run_checks(
  File "/usr/local/lib/python3.8/dist-packages/django/core/checks/registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/usr/local/lib/python3.8/dist-packages/django/core/checks/urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "/usr/local/lib/python3.8/dist-packages/django/core/checks/urls.py", line 24, in check_resolver
    return check_method()
  File "/usr/local/lib/python3.8/dist-packages/django/urls/resolvers.py", line 494, in check
    for pattern in self.url_patterns:
  File "/usr/local/lib/python3.8/dist-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.8/dist-packages/django/urls/resolvers.py", line 715, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/usr/local/lib/python3.8/dist-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.8/dist-packages/django/urls/resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango/MyDjango/urls.py", line 7, in <module>
    path('', include(('index.urls', 'index'), namespace='index')),
  File "/usr/local/lib/python3.8/dist-packages/django/urls/conf.py", line 38, in include
    urlconf_module = import_module(urlconf_module)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango/index/urls.py", line 2, in <module>
    from .views import *
  File "/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango/index/views.py", line 3, in <module>
    from .form import PersonInfoForm
  File "/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango/index/form.py", line 4, in <module>
    class PersonInfoForm(forms.ModelForm):
  File "/data/BOOK/Django3 Web应用开发实践【黄永祥】/Django3 Web应用开发实战/chapter8/8.9/MyDjango/index/form.py", line 5, in PersonInfoForm
    certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': True}))
  File "/usr/local/lib/python3.8/dist-packages/django/forms/widgets.py", line 427, in __init__
    raise ValueError(
ValueError: ClearableFileInput doesn't support uploading multiple files.
我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%

在百度和CSDN搜索“ValueError: ClearableFileInput doesn't support uploading multiple files.”没有找到答案,查看了widgets.py 文件,也找不到错在哪里,查看别人都是这么用的,Django 实现多文件批量上传但没有错,为什么到我这就错了

//form.py
class FileInput(Input):
    allow_multiple_selected = False
    input_type = "file"
    needs_multipart_form = True
    template_name = "django/forms/widgets/file.html"

    def __init__(self, attrs=None):
        if (
            attrs is not None
            and not self.allow_multiple_selected
            and attrs.get("multiple", False)
        ):
            raise ValueError(
                "%s doesn't support uploading multiple files."
                % self.__class__.__qualname__
            )
        if self.allow_multiple_selected:
            if attrs is None:
                attrs = {"multiple": True}
            else:
                attrs.setdefault("multiple", True)
        super().__init__(attrs)

    def format_value(self, value):
        """File input never renders a value."""
        return

    def value_from_datadict(self, data, files, name):
        "File widgets take data from FILES, not POST"
        getter = files.get
        if self.allow_multiple_selected:
            try:
                getter = files.getlist
            except AttributeError:
                pass
        return getter(name)

    def value_omitted_from_data(self, data, files, name):
        return name not in files

    def use_required_attribute(self, initial):
        return super().use_required_attribute(initial) and not initial
我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”

解决这个问题,如果原书作者能看到最好,因为他的代码有问题了,可能需要改进!

  • 写回答

2条回答 默认 最新

  • 彩云之南雪域之巅 2023-12-03 21:51
    关注

    刚刚试了下,如果把

    certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': True}))
    

    写成:

    certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': False}))
    

    是不会报错了,但是不能实现上传多个文件了,只能上传1个文件了。因此还是要解决问题。分析了下widegets.py这个文件,

    
    class FileInput(Input):
        allow_multiple_selected = False
        input_type = "file"
        needs_multipart_form = True
        template_name = "django/forms/widgets/file.html"
     
        def __init__(self, attrs=None):
            if (
                attrs is not None
                and not self.allow_multiple_selected
                and attrs.get("multiple", False)
            ):
                raise ValueError(
                    "%s doesn't support uploading multiple files."
                    % self.__class__.__qualname__
                )
            if self.allow_multiple_selected:
                if attrs is None:
                    attrs = {"multiple": True}
                else:
                    attrs.setdefault("multiple", True)
            super().__init__(attrs)
    

    问题的关键是如果要把默认的

    allow_multiple_selected = False
    

    改成

    allow_multiple_selected = True
    

    才行,问题的关键在这,

            if self.allow_multiple_selected:
                if attrs is None:
                    attrs = {"multiple": True}
                else:
                    attrs.setdefault("multiple", True)
    

    只要allow_multiple_selected = True 那么attrs = {"multiple": True} 问题是如何改变allow_multiple_selected这个值呢?

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {% if v.errors %}
            <p>
                数据出错啦,错误信息:{{ v.errors }}
            </p>
        {% else %}
            <form action="" method="post" enctype="multipart/form-data">
            {% csrf_token %}
                <ul>
                    <li>姓名:{{ p.name }}</li>
                    <li>年龄:{{ p.age }}</li>
                    <li>证件:{{ p.certificate }}</li>
                </ul>
                <input type="submit" value="提交">
            </form>
        {% endif %}
    </body>
    </html>
    
    
    

    难道是改变 enctype="multipart/form-data"

     <form action="" method="post" enctype="multipart/form-data">
    

    参考官方的上传多个文件解决问题

    //form.py
    forms.py¶
    from django import forms
    
    
    class MultipleFileInput(forms.ClearableFileInput):
        allow_multiple_selected = True
    
    
    class MultipleFileField(forms.FileField):
        def __init__(self, *args, **kwargs):
            kwargs.setdefault("widget", MultipleFileInput())
            super().__init__(*args, **kwargs)
    
        def clean(self, data, initial=None):
            single_file_clean = super().clean
            if isinstance(data, (list, tuple)):
                result = [single_file_clean(d, initial) for d in data]
            else:
                result = single_file_clean(data, initial)
            return result
    
    
    class FileFieldForm(forms.Form):
        file_field = MultipleFileField()
    

    在我的form.py中加入上述类后,将原来的代码

    certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': False}))  
    

    修改为:

      certificate = MultipleFileField(label='证件', allow_empty_file=True)
    

    解决问题了,不会报错,且能够上传多个文件了!之前向AI提问,但他没有找到官方的这个解决方案,看来AI也需要学习啊,这个官方教程并不难找。
    最终的form.py

      from django import forms
    from .models import *
    
    class MultipleFileInput(forms.ClearableFileInput):
        allow_multiple_selected = True
    
    
    class MultipleFileField(forms.FileField):
        def __init__(self, *args, **kwargs):
            kwargs.setdefault("widget", MultipleFileInput())
            super().__init__(*args, **kwargs)
    
        def clean(self, data, initial=None):
            single_file_clean = super().clean
            if isinstance(data, (list, tuple)):
                result = [single_file_clean(d, initial) for d in data]
            else:
                result = single_file_clean(data, initial)
            return result
    
    
    class FileFieldForm(forms.Form):
        file_field = MultipleFileField()
    
    
    class PersonInfoForm(forms.ModelForm):
        #certificate = forms.FileField(label='证件', allow_empty_file=True, widget=forms.ClearableFileInput(attrs={'multiple': False}))
        certificate = MultipleFileField(label='证件', allow_empty_file=True)
    
        class Meta:
            model = PersonInfo
            fields = '__all__'
            labels = {
                'name': '名字',
                'age': '年龄',
            }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 12月11日
  • 已采纳回答 12月3日
  • 创建了问题 12月3日

悬赏问题

  • ¥15 关于大棚监测的pcb板设计
  • ¥20 sim800c模块 at指令及平台
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计