【问题标题】:Upgrade to django 1.7 - instance becomes unicode升级到 django 1.7 - 实例变为 unicode
【发布时间】:2014-11-27 14:29:19
【问题描述】:

我最近从 django 1.2.5 迁移到 1.7.0(早就应该升级),正如预期的那样,很多东西都坏了。我已经能够解决很多问题,但是我遇到了一个主要问题。

我将腌制对象存储在数据库中。在 django 1.2.5 中,我运行了以下命令,结果如下

>>> from app.foo.models import MyModel as s
>>> s.objects.get(id = 34567)
<MyModel: Foo (bar)>
>>> x = s.objects.get(id = 34567)
>>> x.myObject
<foor.bar.My Class instance at 0x3855878>
>>> y = x.myObject 
>>> type(y)
<type 'instance'>

但是在 django 1.7.0 上我得到以下内容

>>> from app.foo.models import MyModel as s
>>> s.objects.get(id = 34567)
<MyModel: Foo (bar)>
>>> x = s.objects.get(id = 34567)
>>> x.myObject

VHJlZUFuc3dlckNob2ljZQpwMjYyCihkcDI2MwpnNDEKUydXZWJzaXRlJwpwMjY0CnNnNDMKKGxwMjY1CnNiYShpbm9lLnN1cnZleTIudHJlZXN1cnZleQpUcmVlQW5zd2VyQ2hvaWNlCnAyNjYKKGRwMjY3Cmc0MQpTJ0VwYXBlcicKcDI2OApzZzQzCihscDI2OQpzYmEoaW5vZS5zdXJ2ZXkyLnRyZWVzdXJ2ZXkKVHJlZUFuc3dlckNob2ljZQpwMjcwCihkcDI3MQpnNDEKUydETiBTYWZhcmljb20gTW9iaWxlIEFwcCcKcDI3MgpzZzQzCihscDI3MwpzYmEoaW5vZS5zdXJ2ZXkyLnRyZWVzdXJ2ZXkKVHJlZUFuc3dlckNob2ljZQpwMjc0CihkcDI3NQpnNDEKUydPdGhlcicKcDI3NgpzZzQzCihscDI3NwpzYmFzZzYKZzEKc2cxMQpOc2c2NQpJMDEKc2c5ClMnMScKc2JhZzEyMQphZzEyOQphZzE2NQphZzE3MwphZzE4MAphZzE5MgphZzQKYXNTJ2N1cnJlbnRRdWVzdGlvbicKcDI3OApnNApzUydzZW5kRW5kTWVzc2FnZScKcDI3OQpJMDEKc1MnY2FuU2VuZEVuZE1lc3NhZ2UnCnAyODAKSTAxCnNTJ2Nob2ljZVF1ZXVlJwpwMjgxCihscDI4MgpzYi4='

(这是实际输出的sn-p)

>>> y = x.myObject 
>>> type(y)
<type 'unicode'>

因此,我无法访问实例方法。当我从 1.7 检查对象的属性时,我得到了

>>> dir(y)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'islower', 'isnumeric', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

这是我的模型:

from django.db import models
from django.contrib.auth.models import User
from SerializedDataField import SerializedDataFiel

class MyModel(models.Model):

    title = models.TextField()
    description = models.TextField()
    creator = models.ForeignKey(User)
    created = models.DateTimeField(auto_now_add = True)
    code = models.TextField()
    active = models.BooleanField(default = None)

    """Pickled fresh survey object."""
    myObject = SerializedDataField()

    """Can the pickled surveyObj be changed? Once a survey has been activated, myObject cannot be changed"""
    mutable = models.BooleanField(default = None)      

    def __unicode__(self):
        return self.title + " (" + self.code + ")"

这里是序列化数据字段

from django.db import models
try:
    import cPickle as pickle
except:
    import pickle

import base64

class SerializedDataField(models.TextField):
    """Because Django for some reason feels its needed to repeatedly call
    to_python even after it's been converted this does not support strings."""
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        if value is None: return 
        if not isinstance(value, basestring): return value
        try:
            value = pickle.loads(base64.b64decode(value))
            return value
        except:
            return value

    def get_db_prep_save(self, value *args, **kwargs):
        if value is None: return 
        return base64.b64encode(pickle.dumps(value))

如果我不断得到一个 unicode 对象,我如何访问我的实例方法?

【问题讨论】:

  • 请告诉我们MyModel 模型。
  • 我已将其添加到问题中

标签: python django unicode


【解决方案1】:

所有 Django 中的文本列存储为 Unicode 数据。如果您的列确实是二进制数据,您现在可以将它们迁移到BinaryField(该字段仅在 Django 1.6 中添加)。

对于您现有的数据,您需要编码回二进制字节字符串,您可以使用Latin-1 (ISO 8859-1) 编解码器这样做; Unicode 代码点 U+0000 到 U+00FF 一对一映射到 Latin-1 字节:

y = x.surveyObject.encode('latin1')

当时的错误是将二进制数据视为文本;一开始就不是文字。

【讨论】:

    【解决方案2】:

    我终于明白了。通过迁移,我们还重新订购了应用程序。代码在序列化数据字段中失败

        try:
            value = pickle.loads(base64.b64decode(value))
            return value
        except:
            return value
    

    由于我们已经在数据库中存储了腌制对象,因此在尝试取消腌制对象时,解码失败,因为某些依赖项发生了变化。由于未拾取的对象是在失败的情况下返回的,所以我们得到了 unicode 数据。

    要解决此问题,我必须将已移动的应用恢复到其原始位置,以确保序列化字段能够找到它所依赖的包。

    感谢您的帮助。

    【讨论】:

    • 所以隐藏重要事情的裸except:又来了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 2016-10-23
    相关资源
    最近更新 更多