开发者

AppEngine -> "AttributeError: 'unicode' object has no attribute 'has_key'" when using blobstore

开发者 https://www.devze.com 2023-01-22 12:52 出处:网络
There have been a number of other questions on AttributeErrors here, but I\'ve read through them and am still not sure what\'s causing the type mismatch in my specific case.

There have been a number of other questions on AttributeErrors here, but I've read through them and am still not sure what's causing the type mismatch in my specific case.

Thanks in advance for any thoughts on this.

My model:

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()

My BlobstoreUploadHandler:

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')

And every time I submit the form that uploads the file, it throws the following exception:

ERROR    2010-10-30 21:31:01,045 __init__.py:391] 'unicode' o开发者_运维问答bject 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'

What perplexes me most is that this code is nearly straight out of the documentation, and jives with other examples of blob upload handler's I've found online in tutorials as well.

I've run --clear-datastore to ensure that any changes I've made to the DB schema aren't causing problems, and have tried casting upload_file as all sorts of things to see if it would appease Python - any ideas on what I've screwed up?


Edit: I've found a workaround, but it's suboptimal.

Altering the UploadHandler to this instead resolves the issue:

  ...
  # 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)
  ...

I made this switch after noticing that commenting out the files line threw the same issues for the other line, and so on. This isn't an optimal solution, though, as I can't enforce validation this way (in the model, if I set anything as required, I can't declare an empty entity like above without throwing an exception).

Any thoughts on why I can't declare the entity and populate it at the same time?


You're passing in o as the value of other_item (in your sample code, you call it other, but I presume that's a typo). o is a string fetched from the request, though, and the model definition specifies that it's a ReferenceProperty, so it should either be an instance of the Other class, or a db.Key object.

If o is supposed to be a stringified key, pass in db.Key(o) instead, to deserialize it.

Object is a really terrible name for a datastore class (or any class, really), by the way - the Python base object is called object, and that's only one capitalized letter away - very easy to mistake.


has_key error is due to the ReferenceProperty other_items. You are most likely passing in '' for other_items when appengine's api expects a dict. In order to get around this, you need to convert other_items to hash.


[caveat lector: I know zilch about "google_app_engine"]

The message indicates that it is expecting a dict (the only known object that has a has_key attribute) or a work-alike object, not the unicode object that you supplied. Perhaps you should be passing upload_file, not upload_file.key() ...

0

精彩评论

暂无评论...
验证码 换一张
取 消