2

今日、私はDjangoadminを介してエンコードできないデータを受け取りました。どういうわけか、データのエンコーディングはユニコードではありません。これはどのように可能ですか?

モデルに、データをUnicodeで返すnameプロパティがあります。Client

@property
def name(self):
    return u'{0} {1}'.format(self.firstname, self.lastname).strip()

しかし、これは機能しません:

>>> client
<Client: [Bad Unicode data]>

>>> client.lastname
'Dani\xc3\xabl'

>>> client.lastname.__class__
<type 'str'>

>>> u"{0} {1}".format(client.firstname, client.lastname)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

通常の文字列として名/姓をエンコードすると、十分に機能します。

>>> "{0} {1}".format(client.firstname, client.lastname)
'Test Dani\xc3\xabl'

>>> "{0} {1}".format(client.firstname, client.lastname).decode('utf-8')
u'Test Dani\xebl'

ここで何が起こったのですか?そして、この入力はどのようにして管理者を介して私のモデルに反映されましたか?

システムスタック(これは外部サーバーです):

  • Debian 6.0.5(スクイーズ)
  • Django 1.4.1
  • Python 2.6.6
  • MySQL 5.1.49
  • MySQL-python == 1.2.2

関連するモデルコードは次のとおりです。

class Client(models.Model):
    firstname = models.CharField(_("Firstname"), max_length=255)
    lastname = models.CharField(_("Lastname"), max_length=255)
    email = models.EmailField(_("Email"), unique=True, max_length=255)

    class Meta:
        db_table = u'clients'
        ordering = ('firstname', 'lastname', 'email')

    def __unicode__(self):
        return u'{0} <{1}>'.format(self.name, self.email)

    @property
    def name(self):
        return u'{0} {1}'.format(self.firstname, self.lastname).strip()
4

1 に答える 1

3

これは、MySQLデータベースに使用している照合が原因である可能性があります。

実際、Djangoの動作はunicode、データベースからデータを取得するときに常に文字列を返すことです。これは、コードに問題がないため、コードで機能します。

ただし、データベース設定に関するdjangoのドキュメントでわかるように、セクション照合設定では、照合されたMySQLデータベースでMySQLdbバージョン1.2.2を使用すると、utf8_binデータベースからcharfieldを取得するときに、Unicode文字列ではなくバイト文字列を取得します。

この問題を調査する(つまり、MySQL照合設定を確認する)こともできますが、問題はそこから発生している可能性があります。

この場合、MySQLから取得した入力を手動でデコードする必要があります。または、データベースの照合設定を変更することもできます。

SHOW TABLE STATUS FROM %YOURDB%データベース内のテーブルの照合を取得するために使用できます。


 関連するドキュメントセクションからの抜粋:

デフォルトでは、UTF-8データベースでは、MySQLはutf8_general_ci_swedish照合を使用します。これにより、すべての文字列の等価性の比較で大文字と小文字が区別されません。つまり、「Fred」と「freD」はデータベースレベルで等しいと見なされます。フィールドに一意性制約がある場合、「aa」と「AA」の両方を同じ列に挿入しようとすることは違法です。これらはデフォルトの照合と等しい(したがって、一意ではない)と比較されるためです。

多くの場合、このデフォルトは問題になりません。ただし、特定の列またはテーブルで大文字と小文字を区別する比較が本当に必要な場合は、utf8_bin照合を使用するように列またはテーブルを変更します。この場合に注意すべき主なことは、MySQLdb 1.2.2を使用している場合、Djangoのデータベースバックエンドは、データベースから受け取ったすべての文字フィールドに対して(ユニコード文字列ではなく)バイト文字列を返すことです。これは、常にユニコード文字列を返すというDjangoの通常の慣行とは大きく異なります。

于 2012-09-01T11:44:38.257 に答える