Python 中“AttributeError: 'unicode' object has no attribute 'has_key'” 意思是什么

5 投票
6 回答
45036 浏览
提问于 2025-04-15 13:47

我想问一下“AttributeError: 'unicode' object has no attribute 'has_key'”是什么意思?以下是完整的错误信息:

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'

让我再多说一点关于这个情况:

  • 首先,我创建了一个叫models.py的文件,里面有一个CMSRequest的数据库模型,这个模型有一个叫country的属性,它引用了CMSCountry这个类。

    class CMSRequest(db.Model):
      country = db.ReferenceProperty(CMSCountry, required=True)
    
    class CMSCountry(db.Model):
      name = db.StringProperty(required=True)
    
  • 然后,我创建了一个批量加载器类,用来把数据导入到CMSCountry中。

  • 在表单中,用户可以从下拉列表中选择国家,选择的结果会被提交并保存到CMSRequest对象中。

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

也许我找到了问题的解决办法,是因为我没有把CMSCountry的提交键转换回来,以便保存到CMSRequest中。

谢谢大家!

6 个回答

2

注意:通常在Python中,“映射”类型(比如字典和类似字典的类……比如各种类型的dbm(索引文件)和一些数据库管理系统/对象关系映射接口……会实现一个has_key()方法。

不知怎么的,你在这个语句中引入了一个Unicode(字符串)对象,而你本来是希望有某种字典或其他映射对象的引用。

一般来说,AttributeError意味着你搞混了对象的绑定(变量赋值)。你给某个对象起了个名字,但这个名字并不是你想要的类型。(有时候这也可能是因为你写错了,比如写成“.haskey()”而不是has_key()……等等)。

顺便说一下,使用has_key()这个方法有点过时了。通常更好的做法是用Python的in运算符来测试你的容器(这会隐式调用__contains__()——而且这个方法可以用于列表、字符串和其他序列,以及映射类型)。

另外,即使value是一个字典,value.has_key()也会报错,因为.has_key()方法需要一个参数。

在你的代码中,我建议你明确测试一下if postedcountry is not None:……或者给你的.get()提供一个(可选的)默认值,用于“postedcountry”。

request没有postedcountry时,你想怎么处理这个情况?你想假设它是从某个特定的默认值发出的?强制重定向到某个页面,让用户提供这个表单元素的值?还是要提醒西班牙宗教法庭?

3

你的问题是,postedcountry是一个字符串,而不是一个国家对象。从self.request.get获取的值是浏览器传递的变量的字符串值。

你需要使用一些GQL来查找一个国家对象。具体怎么做取决于你的HTML表单中的国家字段返回的是什么,是对象键还是国家名称?

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

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

  cmsRequest = models.CMSRequest(country=postedcountry)
6

在这一行:

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

value 是一个 Unicode 字符串。看起来代码是希望它是一个 db.Model 对象。

(从我所看到的,has_keydb.Model 的一个方法,同时也是 Python 字典的一个方法,但这里肯定是 db.Model 的那个,因为它没有传入任何参数。)

你是不是把一个字符串传给了一个期望接收 db.Model 的 GAE API?

撰写回答