6

外部ツールで書き込むことができるsqliteデータベースを使用するdjangoプロジェクトがあります。テキストはUTF-8であると想定されていますが、場合によってはエンコードにエラーが発生します。テキストは外部ソースからのものであるため、エンコーディングを制御できません。はい、外部ソースとデータベースの間に「ラッピングレイヤー」を作成できることは知っていますが、特にデータベースにはすでに多くの「不良」データが含まれているため、これを行う必要はありません。

sqliteの解決策は、text_factoryを次のようなものに変更することです。 lambda x: unicode(x, "utf-8", "ignore")

ただし、Djangoモデルドライバーにこれを伝える方法がわかりません。

私が得る例外は次のとおりです。

'Could not decode to UTF-8 column 'Text' with text' in /var/lib/python-support/python2.5/django/db/backends/sqlite3/base.py in execute

どういうわけか、テキストをUTF-8としてデコードしようとしないようにsqliteドライバーに指示する必要があります(少なくとも標準アルゴリズムを使用していませんが、フェイルセーフバリアントを使用する必要があります)。

4

6 に答える 6

9

sqliteの解決策は、text_factoryを次のように変更することです。lambdax:unicode(x、 "utf-8"、 "ignore")

ただし、Djangoモデルドライバーにこれを伝える方法がわかりません。

やってみました

from django.db import connection
connection.connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")

クエリを実行する前に?

于 2010-06-18T21:11:35.800 に答える
2

Millaの答えに触発されて、より寛容なtext_factoryをdjangosqlite接続にインストールする次のモンキーパッチを検討してください。テキストをsqliteデータベースに追加する方法を制御できず、utf-8にない可能性がある場合に使用します。もちろん、ここで使用されているエンコーディングは正しいものではないかもしれませんが、少なくともアプリケーションがクラッシュすることはありません。

import types
from django.db.backends.sqlite3.base import DatabaseWrapper

def to_unicode( s ):
    ''' Try a number of encodings in an attempt to convert the text to unicode. '''
    if isinstance( s, unicode ):
        return s
    if not isinstance( s, str ):
        return unicode(s)

    # Put the encodings you expect here in sequence.
    # Right-to-left charsets are not included in the following list.
    # Not all of these may be necessary - don't know.
    encodings = (
        'utf-8',
        'iso-8859-1', 'iso-8859-2', 'iso-8859-3',
        'iso-8859-4', 'iso-8859-5',
        'iso-8859-7', 'iso-8859-8', 'iso-8859-9',
        'iso-8859-10', 'iso-8859-11',
        'iso-8859-13', 'iso-8859-14', 'iso-8859-15',
        'windows-1250', 'windows-1251', 'windows-1252',
        'windows-1253', 'windows-1254', 'windows-1255',
        'windows-1257', 'windows-1258',
        'utf-8',     # Include utf8 again for the final exception.
    )
    for encoding in encodings:
        try:
            return unicode( s, encoding )
        except UnicodeDecodeError as e:
            pass
    raise e

if not hasattr(DatabaseWrapper, 'get_new_connection_is_patched'):
    _get_new_connection = DatabaseWrapper.get_new_connection
    def _get_new_connection_tolerant(self, conn_params):
        conn = _get_new_connection( self, conn_params )
        conn.text_factory = to_unicode
        return conn

    DatabaseWrapper.get_new_connection = types.MethodType( _get_new_connection_tolerant, None, DatabaseWrapper )
    DatabaseWrapper.get_new_connection_is_patched = True
于 2015-03-01T14:29:06.887 に答える
0

Djangoのmagicstr関数の1つを使用してデータをフィードします。

smart_str(s, encoding='utf-8', strings_only=False, errors='strict')

また

smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')
于 2010-04-30T13:16:28.143 に答える
0

この問題は非常に頻繁に発生し、多くの人にとって非常に興味深いもののようです。(この質問には1000以上のビューがあり、かなりの賛成票があります)

だからここに私が問題に対して見つけた答えがあります、それは私にとって最も便利なものとして見えます:

django sqlite3コネクタを確認し、str変換をget_new_connection(...)関数に直接追加しました。

def get_new_connection(self, conn_params):
    conn = Database.connect(**conn_params)
    conn.create_function("django_date_extract", 2, _sqlite_date_extract)
    conn.create_function("django_date_trunc", 2, _sqlite_date_trunc)
    conn.create_function("django_datetime_extract", 3, _sqlite_datetime_extract)
    conn.create_function("django_datetime_trunc", 3, _sqlite_datetime_trunc)
    conn.create_function("regexp", 2, _sqlite_regexp)
    conn.create_function("django_format_dtdelta", 5, _sqlite_format_dtdelta)
    conn.text_factory = str
    return conn

正常に機能しているようで、すべてのリクエストでユニコードの問題を個別にチェックする必要はありません。これをdjangoコード(?)に追加することを検討するべきではありません。なぜなら、実際にdjangoバックエンドコードを手動で変更することを誰にも勧めないからです...

于 2013-11-13T22:39:22.043 に答える
0
from django.db import connection
connection.cursor()
connection.connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")

私の特定のケースでは、connection.connection.text_factory=strを設定する必要がありました

于 2014-09-22T14:15:08.040 に答える
0

互換性のないDjangoバージョン。このエラーを最初に解決するには、Djangoのバージョンを確認してください。Django == 3.0.8で実行していましたが、エラーが発生していました。私がDjango==3.1.2を持っているvirtualenvを実行したよりも、エラーは削除されました。

于 2020-10-08T13:24:14.943 に答える