2010-06-04 37 views
6

Tôi đang gặp sự cố khi lưu và xuất một ký tự ndash như UTF-8 ở Django.Django đôi có mã hóa chuỗi Unicode (utf-8?) Không?

Tôi đang nhận dữ liệu từ API. Ở dạng thô, như lấy ra và xem trong một trình soạn thảo văn bản, do đơn vị dữ liệu có thể tương tự như:

"I love this detergent \u2013 it is so inspiring." 

(\ u2013 là & ndash; như một thực thể html).

Nếu tôi nhận được điều này trực tiếp từ một API và hiển thị nó ở Django, không có vấn đề gì. Nó hiển thị trong trình duyệt của tôi như một dấu gạch ngang dài. Tôi nhận thấy tôi phải làm decode('utf-8') để tránh các "'ascii' codec không thể mã hóa ký tự" lỗi nếu tôi cố gắng để làm một số hoạt động với văn bản đó trong quan điểm của tôi, mặc dù. Các văn bản sẽ đi đến mẫu là "Tôi yêu chất tẩy rửa này \ u2013 nó rất cảm hứng.", Theo Thanh công cụ gỡ lỗi Django.

Khi được lưu trữ để MySQL và đọc cho đầu ra thông qua quan điểm tương tự và mẫu, tuy nhiên, nó sẽ trông như

"I love this detergent – it is so inspiring" 

bảng MySQL của tôi được thiết lập để DEFAULT CHARSET=utf8.

Bây giờ, khi tôi đọc dữ liệu từ cơ sở dữ liệu thông qua màn hình MySQL trong một thiết bị đầu cuối thiết lập để UTF-8, nó xuất hiện như

"I love this detergent – it is so inspiring" 

(đúng - cho thấy một ndash)

Khi tôi sử dụng mysqldb trong một vỏ python, dòng này là

"I love this detergent \xe2\x80\x93 it is so inspiring" 

(đây là UTF-8 chính xác cho ndash)

Tuy nhiên, nếu tôi chạy python manage.py shell, và sau đó

In [1]: import myproject.myapp.models ThatTable 
In [2]: msg=ThatTable.objects.all().filter(thefield__contains='detergent') 
In [3]: msg 
Out[4]: [{'thefield': 'I love this detergent \xc3\xa2\xe2\x82\xac\xe2\x80\x9c it is so inspiring'}] 

Nó xuất hiện với tôi rằng Django đã \xe2\x80\x93 để có nghĩa là ba nhân vật riêng biệt, và mã hóa nó như là UTF-8 vào \xc3\xa2\xe2\x82\xac\xe2\x80\x9c. Điều này hiển thị là “vì \ xe2 dường như là â, \ x80 có vẻ là €, v.v. Tôi đã kiểm tra và điều này cũng là cách thức nó được gửi tới mẫu.

Nếu bạn giải mã chuỗi dài trong Python, mặc dù, với decode('utf-8'), kết quả là \xe2\u20ac\u201c cũng hiển thị trong trình duyệt dưới dạng â € “. Cố gắng giải mã nó một lần nữa mang lại một UnicodeDecodeError.

Tôi đã theo dõi Django suggestions for Unicode, theo như tôi biết (được định cấu hình MySQL).

Bất kỳ đề xuất nào về những gì tôi có thể đã định cấu hình sai?

phụ lục Có vẻ như vấn đề này cùng đã nảy sinh trong các lĩnh vực khác hoặc hệ thống là tốt., Như khi tìm kiếm \ xc3 \ xa2 \ xe2 \ x82 \ xac \ xe2 \ x80 \ x9c, tôi thấy ở http://pastie.org/908443.txt một kịch bản để 'sửa chữa các thực thể UTF8 xấu.', cũng được tìm thấy trong một trình cắm nhập RSS wordpress. Nó đơn giản thay thế trình tự này bằng –. Tôi muốn giải quyết điều này đúng cách, mặc dù!

Ồ, và tôi đang sử dụng Django 1.2 và Python 2.6.5.

Tôi có thể kết nối với cùng một cơ sở dữ liệu với PHP/PDO và in ra dữ liệu này mà không thực hiện bất kỳ điều gì đặc biệt và có vẻ ổn.

Trả lời

1

Điều này có vẻ giống như trường hợp mã hóa kép; Tôi không có nhiều kinh nghiệm với Python, nhưng hãy thử điều chỉnh cài đặt kết nối MySQL theo lời khuyên tại http://tahpot.blogspot.com/2005/06/mysql-and-python-and-unicode.html

Điều tôi đoán đang xảy ra là kết nối là latin1, vì vậy MySQL cố gắng mã hóa chuỗi lại trước lưu trữ vào trường UTF-8. Mã này có, đặc biệt là bit này:

EDIT: Với Python khi thiết lập một kết nối cơ sở dữ liệu thêm cờ sau: init_command = 'TÊN SET utf8'.

Bên cạnh đó thiết lập sau đây trong my.cnf của MySQL: mặc định ký tự thiết lập = utf8

có lẽ là những gì bạn muốn.

+0

Thật kỳ lạ, nhưng gọi 'tên đặt utf8' làm cho vấn đề trở nên tồi tệ hơn. Để lại Django ra khỏi hình ảnh, trong một vỏ Python, nó làm cho nhân vật đó là '\ xc3 \ xa2 \ xe2 \ x82 \ xac \ xe2 \ x80 \ x9c'. sau đó nếu tôi gọi 'set name latin1', ký tự trở thành' \ xe2 \ x80 \ x93'. Trong PHP, nó đi từ â € “đến à ¢ â 'â € œ. Vì vậy, việc đặt nó thành latin1 thực sự làm cho nó hoạt động tốt trong PHP. Tôi khá chắc chắn rằng Django gọi 'đặt tên utf8' để chuẩn bị kết nối, thực sự. – JAL

+1

Aha, có vẻ như tôi cần gọi 'set name' trước khi chèn dữ liệu. – JAL

+0

Chèn dữ liệu vào php, nghĩa là. Tôi sẽ tiếp tục và chấp nhận câu trả lời của bạn (mặc dù tôi cần lưu ý cho người đọc trong tương lai, giải pháp là gọi 'set names utf8' cho kết nối PHP, không phải là tên Python) – JAL

0

Tôi đã thêm set names utf8 vào chuỗi chèn dữ liệu php của mình và bây giờ trong một trình bao Python, ndash đáng sợ xuất hiện dưới dạng \ x96. Điều này hiển thị chính xác khi đọc và xuất thông qua Django.

Một tình huống bất thường về việc này là tôi đang chèn dữ liệu qua PHP. Các vấn đề Django set names utf8 tự động, vì vậy có khả năng nếu tôi chèn và đọc dữ liệu qua Django, vấn đề này sẽ không xuất hiện. PHP đã sử dụng mặc định là latin1, tôi giả sử

Như một lưu ý thú vị, trong khi trước đây tôi có thể đọc dữ liệu từ PHP và nó hiển thị bình thường trong trình duyệt, bây giờ ndash là trừ khi tôi gọi set names trước khi đọc dữ liệu .

Vì vậy, nó hoạt động ngay bây giờ và tôi hy vọng tôi không bao giờ phải hiểu bất cứ điều gì đã xảy ra trước đây!

+0

Vâng, đó sẽ là vấn đề với bạn dữ liệu cũ. Nếu bạn có thể đủ khả năng để đưa DB của bạn ẩn một chút, bạn có thể thay đổi các cột có chuỗi trở lại latin1; sau đó, đặt chúng thành các đốm màu; sau đó, đặt chúng trở lại utf8. Điều này sẽ khắc phục các chuỗi được mã hóa kép cũ. – phsource

+0

Rất may, tôi đã bắt được tất cả những điều này trong giai đoạn phát triển, vì vậy tôi có sự linh hoạt để thả, cắt ngắn và tạo lại các bảng để kiểm tra mọi thứ. Điều đó có thể có ích cho phần còn lại của trang web, mặc dù ... Tôi không biết liệu chúng tôi có dữ liệu khác bị mã hóa sai hay không. Cảm ơn bạn đã biết cách thực hiện điều đó. – JAL

Các vấn đề liên quan