【问题标题】:Django 1.5 raises UnicodeDecodeError when persisting uploaded fileDjango 1.5 在持久化上传文件时引发 UnicodeDecodeError
【发布时间】:2013-09-26 05:20:04
【问题描述】:

当我将项目的 django 版本更新到 1.5.x 时,开始出现此问题。

我的问题是,当使用 mysql 作为后端时,我上传了一个文件并尝试将该文件的块保存到另一个模型上,我得到一个 UnicodeDecodeError。

在 django 1.4.x 中没有抛出任何错误,并且相关模型被持久化。

要重新创建的示例项目: https://github.com/imtapps/fileuploaderror

models.py

from django.db import models

class LongBlob(models.Field):
    def db_type(self, connection):
        return "longblob"   

class Document(models.Model):
    document = LongBlob()

class Book(models.Model):
    description = models.CharField(max_length=30)
    document = models.ForeignKey(Document, null=True)

forms.py

from django import forms
from spikeapp.models import Document, Book

class BookForm(forms.ModelForm):
    upload_file = forms.FileField()

    def save(self, *args, **kwargs):
        self.cleaned_data['upload_file'].open()
        data = ''.join([chunk for chunk in self.cleaned_data['upload_file'].chunks()])
        self.cleaned_data['upload_file'].close()
        Document.objects.create(document=data)

    class Meta:
        model = Book
        fields = ('description',)

views.py

from django.views.generic.edit import FormView
from spikeapp.forms import BookForm

class FileView(FormView):
    template_name = 'file.html'
    form_class = BookForm
    success_url = "/"

    def form_valid(self, form):
        form.save()
        return super(FileView, self).form_valid(form)

这是个例外:

Traceback:
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  86.         return handler(request, *args, **kwargs)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/views/generic/edit.py" in post
  165.             return self.form_valid(form)
File "/home/appsdev/Projects/blobspike/spikeapp/views.py" in form_valid
  11.         form.save()
File "/home/appsdev/Projects/blobspike/spikeapp/forms.py" in save
  12.         Document.objects.create(document=data)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/manager.py" in create
  149.         return self.get_query_set().create(**kwargs)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/query.py" in create
  416.         obj.save(force_insert=True, using=self.db)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/base.py" in save
  546.                        force_update=force_update, update_fields=update_fields)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/base.py" in save_base
  650.                 result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/manager.py" in _insert
  215.         return insert_query(self.model, objs, fields, **kwargs)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/query.py" in insert_query
  1675.     return query.get_compiler(using=using).execute_sql(return_id)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
  937.             cursor.execute(sql, params)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/backends/util.py" in execute
  45.             sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "/home/appsdev/.virtualenvs/blobspike/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py" in last_executed_query
  243.         return cursor._last_executed.decode('utf-8')
File "/home/appsdev/.virtualenvs/blobspike/lib/python2.7/encodings/utf_8.py" in decode
  16.     return codecs.utf_8_decode(input, errors, True)

Exception Type: UnicodeDecodeError at /
Exception Value: 'utf8' codec can't decode byte 0xb5 in position 67: invalid start byte

要复制的版本: MySQLdb-Python = 1.2.4

Django = 1.5.4

【问题讨论】:

  • 你能给我们完整的追溯吗?在调试错误视图中,有一个链接可以切换到可复制的纯文本回溯。
  • 什么版本的 Python?
  • 我使用的是 2.7.4 版
  • 有趣的是,1.5 失败的是记录执行的查询,不是插入数据。

标签: python mysql django python-2.7 django-forms


【解决方案1】:

您偶然发现了 Django 1.5 中的一个错误:#19954 Storing of Binary fields leads to Exceptions

committed fix 是用“替换”强制解码最后执行的查询:

return force_text(cursor._last_executed, errors='replace')

您可以编辑 Django 源代码,或应用猴子补丁:

from django.utils.encoding import force_text
from django.db.backends.mysql.base import DatabaseOperations

def fixed_last_executed_query(self, cursor, sql, params):
    return force_text(cursor._last_executed, errors='replace')

DatabaseOperations.last_executed_query = fixed_last_executed_query

尽早这样做,例如,在 settings 模块或包的顶部。

我认为补丁没有被反向移植;到目前为止,它只进入了 1.6 的开发线,可能是因为 1.6 添加了新的 Binary 字段类型。

【讨论】:

  • 哇!我希望我能给你一千个赞。这完全解决了我的问题。非常感谢马丁。我们将只分叉我们的 django 源代码。
  • 我无法让它工作。我尝试直接编辑 django 代码,就像在“提交的修复”中一样,也尝试将上面的代码片段放入我的设置中,但都没有奏效。 - 有什么建议吗?
  • 如果没有关于您的设置的回溯和更多详细信息,几乎不可能说出为什么这对您不起作用。对不起!
猜你喜欢
  • 2022-07-21
  • 1970-01-01
  • 2014-05-14
  • 2013-11-21
  • 1970-01-01
  • 2017-09-26
  • 2019-10-13
  • 1970-01-01
  • 2020-04-05
相关资源
最近更新 更多