Django - 'TypeError: expected string or bytes-like object' when clearing an uploaded image with Cloudinary
我正在Django应用程序中使用Cloudinary来存储和服务用户在我的站点的一个视图中上载的图像。图像将被正确上载和显示;但是,在我的更新视图中,当用户选中"清除"以删除上一个图像,然后提交表单时,将显示此错误:
TypeError: expected string or bytes-like object
浏览器中的"错误"页还显示这些突出显示的消息:
...\lib\site-packages\cloudinary\models.py in to_python
return self.parse_cloudinary_resource(value) ......\lib\site-packages\cloudinary\models.py in parse_cloudinary_resource
m = re.match(CLOUDINARY_FIELD_DB_RE, value) ......\AppData\Local\Programs\Python\Python36-32\lib
e.py in match
return _compile(pattern, flags).match(string)
以下是我的模型、视图和表单的外观:
模型:
1 2 3 | class Item(models.Model): name = models.CharField(max_length=255) image1 = CloudinaryField('image', blank=True, null=True) |
VIEW
1 2 3 | class ItemUpdateView(LoginRequiredMixin, UpdateView): model = models.Item form_class = forms.ItemForm |
表单
1 2 3 4 5 6 7 | class ItemForm(forms.ModelForm): image1 = CloudinaryFileField( required=False, options = {'crop': 'limit', 'width': 546, 'height': 1000,}) class Meta: model = models.Item fields = ("image1","name") |
我认为当字段值为空时,Cloudinary仍在期待一些东西。我已经查看了文档并搜索了网络,但我无法解决这个问题。
编辑:我检查了我的管理员并试图从那里编辑一个项目,当我选中"清除"复选框并点击"保存"时,得到了相同的错误。因此,问题似乎在于我如何在我的模型上创建IMAGE1字段,因为管理视图将仅依赖于此。但我还是不知道怎么修。
edit2:在"图像"字段上选中"清除"并单击"保存"时的完整回溯,来自管理员:
Environment:
Request Method: POST Request URL:
http://127.0.0.1:8000/admin/items/item/4/change/Django Version: 1.11.1 Python Version: 3.6.1 Installed Applications:
['django.contrib.admin','django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.humanize',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'cloudinary',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.twitter',
'haystack',
'items']
Installed Middleware:
['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']Traceback:
File
"D:\projects\django\gia\lib\site-packages\django\core\handlers\exception.py"
in inner
41. response = get_response(request)File
"D:\projects\django\gia\lib\site-packages\django\core\handlers\base.py"
in _get_response
187. response = self.process_exception_by_middleware(e, request)File
"D:\projects\django\gia\lib\site-packages\django\core\handlers\base.py"
in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)File
"D:\projects\django\gia\lib\site-packages\django\contrib\admin\options.py"
in wrapper
551. return self.admin_site.admin_view(view)(*args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\utils\decorators.py"
in _wrapped_view
149. response = view_func(request, *args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\views\decorators\cache.py"
in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\contrib\admin\sites.py"
in inner
224. return view(request, *args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\contrib\admin\options.py"
in change_view
1511. return self.changeform_view(request, object_id, form_url, extra_context)File
"D:\projects\django\gia\lib\site-packages\django\utils\decorators.py"
in _wrapper
67. return bound_func(*args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\utils\decorators.py"
in _wrapped_view
149. response = view_func(request, *args, **kwargs)File
"D:\projects\django\gia\lib\site-packages\django\utils\decorators.py"
in bound_func
63. return func.get(self, type(self))(*args2, **kwargs2)File
"D:\projects\django\gia\lib\site-packages\django\contrib\admin\options.py"
in changeform_view
1408. return self._changeform_view(request, object_id, form_url, extra_context)File
"D:\projects\django\gia\lib\site-packages\django\contrib\admin\options.py"
in _changeform_view
1440. if form.is_valid():File"D:\projects\django\gia\lib\site-packages\django\forms\forms.py"
in is_valid
183. return self.is_bound and not self.errorsFile"D:\projects\django\gia\lib\site-packages\django\forms\forms.py"
in errors
175. self.full_clean()File"D:\projects\django\gia\lib\site-packages\django\forms\forms.py"
in full_clean
386. self._post_clean()File"D:\projects\django\gia\lib\site-packages\django\forms\models.py"
in _post_clean
396. self.instance.full_clean(exclude=exclude, validate_unique=False)File
"D:\projects\django\gia\lib\site-packages\django\db\models\base.py" in
full_clean
1226. self.clean_fields(exclude=exclude)File
"D:\projects\django\gia\lib\site-packages\django\db\models\base.py" in
clean_fields
1268. setattr(self, f.attname, f.clean(raw_value, self))File
"D:\projects\django\gia\lib\site-packages\django\db\models\fields__init__.py"
in clean
601. value = self.to_python(value)File"D:\projects\django\gia\lib\site-packages\cloudinary\models.py"
in to_python
74. return self.parse_cloudinary_resource(value)File"D:\projects\django\gia\lib\site-packages\cloudinary\models.py"
in parse_cloudinary_resource
50. m = re.match(CLOUDINARY_FIELD_DB_RE, value)File
"C:\Users\samee\AppData\Local\Programs\Python\Python36-32\lib
e.py"
in match
172. return _compile(pattern, flags).match(string)Exception Type: TypeError at /admin/items/item/4/change/ Exception
Value: expected string or bytes-like object
也许有点晚了,但我也遇到了同样的问题,在寻找解决方案的过程中,我偶然发现了这个问题。
我发现验证方法仍然在寻找一个不再存在的对象。通过单击清除按钮,您可以有效地将其从日志背面删除。默认情况下,验证设置为标记此项,因为它正试图清除(验证)不再存在的内容。
你很容易绕过它。只需创建is-valid方法调用的clean方法。这张照片不会再出现了,所以就不回了。下面是一个代码示例:
从我的is_valid():
1 2 | if request.method == 'POST': if picture_form_set.is_valid(): |
它反过来调用clean方法,因此为cloudaniry字段创建一个方法:
1 2 | def clean_picture(self): return self.cleaned_data['picture'] or None |
希望有所帮助
问题在于
Marco Silva对此Github问题的解决方案,https://github.com/cloudinary/pycloudinary/issues/98。
1 2 3 4 5 6 | class CloudinaryFieldFix(CloudinaryField): def to_python(self, value): if value is False: return value else: return super(FixCloudinaryField, self).to_python(value) |