Python what does it mean "AttributeError: 'unicode' object has no attribute 'has_key' "

44,532

Solution 1

In this line:

if value is not None and not value.has_key():

value is a unicode string. It looks like the code is expecting it to be a db.Model,

(From what I can see, has_key is a method of db.Model, as well as a method of Python dictionaries, but this must be the db.Model one because it's being called with no arguments.)

Are you passing a string to a GAE API that expects a db.Model?

Solution 2

Your problem is that postedcountry is a string and not a country object. Values retrieved from self.request.get are the string values of variables passed by the browser.

You need to look up a country object using some GQL. Exactly how you do that will depend on what exactly the country field of your HTML form is returning , Object Key?, country name?

def post(self):
  postedcountry = self.request.get('country')

  # <-------- Need to look up a country here !!!!!

  cmsRequest = models.CMSRequest(country=postedcountry)

Solution 3

Note: normally "mapping" types in Python (dictionaries and dictionary like classes ... such as various types of dbm (indexed file) and some DBMS/ORM interfaces ... will implement a has_key() method.

Somehow you have gotten a Unicode (string) object into this statement when you were expecting to have some sort of dictionary or other mapping object reference.

In general AttributeError means that you have tangled up your object bindings (variable assignments). You've given a name to some object other than the type that you intended. (Or sometimes it means you have a typo like ".haskey()" instead of has_key() ... etc).

BTW: the use of has_key() is somewhat dated. Normally it's better to test your containers with the Python in operator (which implicitly calls __contains__() --- and which works on lists, strings, and other sequences as well as mapping types).

Also value.has_key() would raise an error even if value were a dictionary since the .has_key() method requires an argument.

In your code I would either explicitly test for if postedcountry is not None: ... or I'd supply your .get() with an (optional) default for "postedcountry."

How do you want to handle the situation where request had no postedcountry? Do you want to assume it's being posted from some particular default? Force a redirection to some page that requires the user to supply a value for that form element? Alert the Spanish Inquisition?

Solution 4

If you read the traceback, it'll tell you exactly what is going on:

    if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'

What this says is the the value variable which you're using doesn't have the has_key attribute. And, what it's telling you is that your value variable isn't a dictionary, as it looks like you're expecting...instead, it's a unicode object, which is basically a string.

Solution 5

You're attempting to set a string to a ReferenceProperty. The 'country' field of CMSCountry is a db.ReferenceProperty, which takes a db.Key or a CMSCountry object, but you're attempting to set it to a string.

You should be doing something like this:

def post(self):
  postedcountry = self.request.get('country')
  country = models.CMSCountry.all().filter('name =', postedcountry)
  if not country:
    # Couldn't find the country
  else:
    cmsRequest = models.CMSRequest(country=country)

Please do file a bug about the rather unhelpful error message, though.

Share:
44,532
Hoang Pham
Author by

Hoang Pham

I was born in Vietnam, currently live in Milan, Italy. I am a software developer with strong iOS experience. I have learned the following softwares/languages/tools/technologies: – Operating systems: Mac OS X, Linux Ubuntu, Windows – Programming languages: Objective-C, C, C , C#, Python, Ruby, Java, Bash Script – Data exchange languages: JSON, XML – Versioning control systems: Git version control GitX – Database management systems: Sql Server, Sqlite3 – Integrated development environment: Xcode 3, Xcode 4, Eclipse, Visual Studio. – Application frameworks: Cocoa Touch, Google App Engine, Ruby on Rails, .net, Eclipse Graphical Modeling Framework, Eclipse Modeling Framework, J2ME, Django, DotNetNuke – Debugger tools: Xcode, gcc, gdb. – Editors: TextMate, Vi, Latex, Microsoft Word, Excel, Powerpoint, MarsEdit. – Image editing tools: Photoshop – Diagram editors: Omnigraffle Professional, Microsoft Visio – Blogging softwares: WordPress, Tumblr. – Web technologies: HTML, CSS, jQuery, XSLT, eXSLT, Firebug, Charles HTTP Debugger – Others: Crystal Report, Reporting Services. My profiles and websites: http://github.com/pnhoang http://twitter.com/pnhoang

Updated on October 09, 2020

Comments

  • Hoang Pham
    Hoang Pham over 3 years

    I would like to ask what does it mean "AttributeError: 'unicode' object has no attribute 'has_key'" Here is the full stack trace:

    Traceback (most recent call last):
      File     "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\webapp\__init__.py", line 509, in __call__
        handler.post(*groups)
      File "D:\Projects\workspace\foo\src\homepage.py", line 71, in post
        country=postedcountry
      File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 656, in __init__
        prop.__set__(self, value)
      File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 2712, in __set__
        value = self.validate(value)
      File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 2742, in validate
        if value is not None and not value.has_key():
    AttributeError: 'unicode' object has no attribute 'has_key'
    

    Let me describe a little bit more about the situation:

    • First I created the models.py that has the db.Model for CMSRequest which has an attribute country that reference to the CMSCountry class

      class CMSRequest(db.Model):
        country = db.ReferenceProperty(CMSCountry, required=True)
      
      class CMSCountry(db.Model):
        name = db.StringProperty(required=True)
      
    • Then, I created a bulkloader class to import the data into the CMSCountry

    • In the form, user can select the country from the drop down list box, the results are posted back and save to the CMSRequest object

      def post(self):
        postedcountry = self.request.get('country')
        cmsRequest = models.CMSRequest(postedcountry)
      

    Maybe I have found the solution to my question, it is because I have not converted the posted key of CMSCountry back to save to the CMSRequest.

    Thank you everyone!

  • RichieHindle
    RichieHindle over 14 years
    @Hoang: It looks like you need something along the lines of cmsRequest = models.CMSRequest(country=models.CMSCountry(postedcountry)) (I don't know whether that's exactly the right way to get a CMSCountry from a string, but you see what I'm saying).
  • Hoang Pham
    Hoang Pham over 14 years
    Thank Richie, based on your suggestion, I have modified the code as following: def post(self): postedcountry = self.request.get('country') country = models.CMSCountry.get(postedcountry) cmsRequest = models.CMSRequest(country) The key of the country should be populated in the html for the options, and postedcountry will have the key of the CMSCountry.