views:

39

answers:

1

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

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?

A: 

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

John Machin
Thanks for the quick response, John. I've tried 'upload_file' instead, but it doesn't work either. Also, this appears to be the way it's set out in the documentation: http://code.google.com/appengine/docs/python/tools/webapp/blobstorehandlers.html
Andrew