AppEngine -> 使用blobstore时出现“AttributeError: 'unicode'对象没有'has_key'属性”

0 投票
3 回答
4476 浏览
提问于 2025-04-16 06:20

这里有很多关于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 个回答

0

[注意:我对“google_app_engine”一无所知]

这个信息的意思是,它在期待一个 dict(这是唯一一个有 has_key 属性的对象)或者一个类似的对象,而不是你提供的 unicode 对象。也许你应该传递 upload_file,而不是 upload_file.key() ...

1

has_key错误是因为ReferenceProperty的other_items。你很可能在传递other_items时用了''(空字符串),而appengine的API其实是希望你传一个字典(dict)。为了避免这个问题,你需要把other_items转换成哈希表(hash)。

2

你把 o 作为 other_item 的值传入了(在你的示例代码中,你叫它 other,但我猜那是个笔误)。不过,o 是从请求中获取的一个字符串,而模型定义说明它应该是 ReferenceProperty,所以它应该是 Other 类的一个实例,或者是一个 db.Key 对象。

如果 o 应该是一个字符串形式的键,那就用 db.Key(o) 来传入,这样可以把它转换回来。

顺便说一下,Object 这个名字对于数据存储类(或者任何类)来说都非常糟糕 - Python 的基础对象叫 object,它们只差一个大写字母,非常容易搞混。

撰写回答