我正在尝试使用python的google api。我已经设法将凭据存储在CredentialsField
(基本上是复制这个)实现中。
我可以得到一个存储对象:
>>> storage = Storage(CredentialsModel, 'id', user, 'credential')
>>> storage
<oauth2client.django_orm.Storage object at 0x7f1f8f1260f0>
没问题。但是当我尝试获取凭据对象时:
>>> credential = storage.get()
>>> credential
我只得到一个巨大的字符串(7482个字符),而不是一个凭据对象。什么东西?(我认为字符串可能是一个字节数组,因为它以'\x67414e6a6
.开头
我也在使用Python 3。
有什么想法吗?为什么我要得到一个字符串而不是Credentials对象?
如果你还需要的话,我已经找到了答案:
问题是django_orm中的类CredentialFields定义了一个元类变量,python3不再支持该变量。
因此,有必要将其更改为以下内容:
class CredentialsField(models.Field,元类=models.SubfieldBase):
有人在github回购中打开了一个问题:
https://github.com/google/oauth2client/issues/168
我的python3、django 1.8解决方案,带有postgres数据库:
在将字节数据保存到数据库之前,以及从数据库检索回数据之后,缺少一个步骤:字节数据需要首先转换为字符串/从字符串转换。您可以使用decode("utf-8")
和encode("utf-8")
将字节转换为字符串,反之亦然。
您也不需要__metaclass__
,但需要具有get_prep_value()
和from_db_value()
函数。整个类CredentialsField
应该这样重写:
class CredentialsField(models.Field):
def __init__(self, *args, **kwargs):
if 'null' not in kwargs:
kwargs['null'] = True
super().__init__(*args, **kwargs)
def get_internal_type(self):
return "TextField"
def to_python(self, value):
if value is None:
return None
if isinstance(value, oauth2client.client.Credentials):
return value
value = value.encode("utf-8") # string to byte
return pickle.loads(base64.b64decode(value))
def from_db_value(self, value, expression, connection, context):
return self.to_python(value)
def get_db_prep_value(self, value, connection, prepared=False):
if value is None:
return None
byte_repr = base64.b64encode(pickle.dumps(value))
return byte_repr.decode("utf-8") # byte to string
def get_prep_value(self, value):
return self.get_db_prep_value(value)