AppEngine -> 使用blobstore时出现“AttributeError: 'unicode'对象没有'has_key'属性”
这里有很多关于AttributeErrors的问题,但我看过之后,还是不太明白在我这个具体情况下,类型不匹配的原因是什么。
提前感谢大家的想法。
我的模型:
class Object(db.Model):
notes = db.StringProperty(multiline=False)
other_item = db.ReferenceProperty(Other)
time = db.DateTimeProperty(auto_now_add=True)
new_files = blobstore.BlobReferenceProperty(required=True)
email = db.EmailProperty()
is_purple = db.BooleanProperty()
我的Blobstore上传处理器:
class FormUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
try:
note = self.request.get('notes')
email_addr = self.request.get('email')
o = self.request.get('other')
upload_file = self.get_uploads()[0]
# Save the object record
new_object = Object(notes=note,
other=o,
email=email_addr,
is_purple=False,
new_files=upload_file.key())
db.put(new_object)
# Redirect to let user know everything's peachy.
self.redirect('/upload_success.html')
except:
self.redirect('/upload_failure.html')
每次我提交上传文件的表单时,它都会抛出以下异常:
ERROR 2010-10-30 21:31:01,045 __init__.py:391] 'unicode' object has no attribute 'has_key'
Traceback (most recent call last):
File "/home/user/Public/dir/google_appengine/google/appengine/ext/webapp/__init__.py", line 513, in __call__
handler.post(*groups)
File "/home/user/Public/dir/myapp/myapp.py", line 187, in post
new_files=upload_file.key())
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 813, in __init__
prop.__set__(self, value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3216, in __set__
value = self.validate(value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3246, in validate
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
让我最困惑的是,这段代码几乎是直接来自文档的,而且和我在网上找到的其他blob上传处理器的示例也很一致。
我运行了--clear-datastore,以确保我对数据库结构所做的任何更改不会导致问题,并尝试将upload_file
转换成各种类型,看看能否让Python满意——你们觉得我哪里搞错了?
编辑:我找到了一种变通办法,但效果不太理想。
将UploadHandler改成这样可以解决问题:
...
# Save the object record
new_object = Object()
new_object.notes = note
new_object.other = o
new_object.email = email.addr
new_object.is_purple = False
new_object.new_files = upload_file.key()
db.put(new_object)
...
我注意到注释掉文件行会导致other
行出现同样的问题,所以做了这个调整。不过,这并不是一个理想的解决方案,因为我无法通过这种方式强制执行验证(在模型中,如果我把某些东西设置为必填项,我就不能像上面那样声明一个空实体,否则会抛出异常)。
你们觉得为什么我不能同时声明实体并填充它呢?
3 个回答
[注意:我对“google_app_engine”一无所知]
这个信息的意思是,它在期待一个 dict
(这是唯一一个有 has_key
属性的对象)或者一个类似的对象,而不是你提供的 unicode
对象。也许你应该传递 upload_file
,而不是 upload_file.key()
...
has_key错误是因为ReferenceProperty的other_items。你很可能在传递other_items时用了''(空字符串),而appengine的API其实是希望你传一个字典(dict)。为了避免这个问题,你需要把other_items转换成哈希表(hash)。
你把 o
作为 other_item
的值传入了(在你的示例代码中,你叫它 other
,但我猜那是个笔误)。不过,o
是从请求中获取的一个字符串,而模型定义说明它应该是 ReferenceProperty
,所以它应该是 Other
类的一个实例,或者是一个 db.Key
对象。
如果 o
应该是一个字符串形式的键,那就用 db.Key(o)
来传入,这样可以把它转换回来。
顺便说一下,Object
这个名字对于数据存储类(或者任何类)来说都非常糟糕 - Python 的基础对象叫 object
,它们只差一个大写字母,非常容易搞混。