Z9G's NOTES

python + c = nuclear

Python中将任意编码的字符串转换成Unicode编码

之前都是用try捕捉异常的方式,试探性的转码, 现在发现其实自己很老土, 原来有更简单的方式:

>>> import chardet
>>> chardet.detect('你好')
{'confidence': 0.75249999999999995, 'encoding': 'utf-8'}
>>> s = '你好'
>>> s.decode(chardet.detect(s)['encoding'])
u'\u4f60\u597d'
>>> type(u'\u4f60\u597d')
<type 'unicode'>

在UTF8的Django项目中输出GBK编码的页面

  最近一个Web项目中涉及到多方合作,不同合作方要求返回的页面编码格式不一样,有的是UTF8,有的是GB2312。但是Django默认只支持一种编码格式,就是在settings.py里面设置的LANGUAGE_CODE,并且Django会自动将输入进来的参数(包括HttpRequest和数据库的读取)decode成Unicode,并在返回的时encode成LANGUAGE_CODE指定的编码。这样尝试在UTF8的项目里面直接输出GB2312的页面就会出现编码错误,返回Django的500页面。
  在翻阅Django文档无果后,翻开Django源码寻求解决方案,Ubuntu下通过apt-get方式安装的Django位于 /usr/share/python-support/python-django/django,因为返回页面涉及到HttpResponse, 所以打开django/http下的__init__.py, 找到HttpResponse的定义:

class HttpResponse(object):
    """A basic HTTP response, with content and dictionary-accessed headers."""

    status_code = 200

    def __init__(self, content='', mimetype=None, status=None,
            content_type=None):
        from django.conf import settings
        self._charset = settings.DEFAULT_CHARSET
        if mimetype:
            content_type = mimetype     # For backwards compatibility
        if not content_type:
            content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE,
                    settings.DEFAULT_CHARSET)
        if not isinstance(content, basestring) and hasattr(content, '__iter__')
            self._container = content
            self._is_string = False
        else:
            self._container = [content]
            self._is_string = True
        self.cookies = SimpleCookie()
        if status:
            self.status_code = status

        # _headers is a mapping of the lower-case name to the original case of
        # the header (required for working with legacy systems) and the header
        # value.
        self._headers = {'content-type': ('Content-Type', content_type)}

在项目里面定义一个派生自HttpResponse的GbkHttpResponse的新类:

from django.http import HttpResponse
from Cookie import SimpleCookie
class GbkHttpResponse(HttpResponse):
    """
    返回GB2312编码的Response
    """
    status_code = 200
    def __init__(self, content='', content_type=None):
        self._charset = 'GB2312'
        content_type = "text/html; charset=GB2312"
        if not isinstance(content, basestring) and hasattr(content, '__iter__'):
            self._container = content
            self._is_string = False
        else:
            self._container = [content]
            self._is_string = True
        self.cookies = SimpleCookie()
        self._headers = {'content-type': ('Content-Type', content_type)}

在需要输出GB2312编码的view里面调用GbkHttpResponse即可(some_view所在的文件是UTF8编码)

def some_view(request):
    return GbkHttpResponse('<html>\n<body>这里将输出GB2312编码的内容\n</body>\n</html>\n'.decode('utf8').encode('gbk'))

解决jQuery在ie下JSON的cache问题

ie会cache jQuery的get请求, 导致jQuery的getJSON的失败, 有两种解决方案:

  1. 服务器端设置http header:
  2. Cache-Control: no-cache
  3. 用POST方式定义 JSON调用
  4. $.postJSON = function(url, data, callback) {
        $.post(url, data, callback, "json");
    }
    

    然后用postJSON 替代 getJSON即可

采用POST的方式实现起来更简单, 推荐使用

Hello world!

This is a beginning.