Python, что это значит "AttributeError: объект 'Unicode' не имеет атрибута 'has_key'" - PullRequest
5 голосов
/ 22 августа 2009

Я хотел бы спросить, что это значит "AttributeError: объект 'Unicode' не имеет атрибута '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 с db.Model для CMSRequest, в котором есть страна атрибутов, ссылающаяся на класс 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 ]

6 голосов
/ 22 августа 2009

В этой строке:

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

value - строка в юникоде. Похоже, код ожидает, что это будет db.Model,

(Из того, что я вижу, has_key - это метод db.Model, а также метод словарей Python, но это должен быть db.Model, потому что он вызывается без аргументов.)

Вы передаете строку в API GAE, которая ожидает db.Model?

3 голосов
/ 23 августа 2009

Ваша проблема в том, что postscountry - это строка, а не объект страны. Значения, полученные из 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)
2 голосов
/ 22 августа 2009

Примечание: обычно "отображающие" типы в Python (словари и словарные классы ... такие как различные типы dbm (индексированный файл) и некоторые интерфейсы СУБД / ORM ... реализуют метод has_key().

Каким-то образом вы добавили объект Unicode (строковый) в этот оператор, когда вы ожидали получить какой-либо словарь или другую ссылку на объект сопоставления.

В общем случае AttributeError означает, что вы запутали привязки объектов (присвоения переменных). Вы дали имя некоторому объекту, отличному от того, который вы намеревались. (Или иногда это означает, что вместо has_key() ... и т. Д. У вас есть опечатка типа .haskey ()).

Кстати: использование has_key() несколько устарело. Обычно лучше тестировать ваши контейнеры с помощью оператора Python in (который неявно вызывает __contains__() --- и который работает со списками, строками и другими последовательностями, а также с типами отображения).

Также value.has_key() вызовет ошибку, даже если value будет словарём, так как метод .has_key() требует аргумента.

В вашем коде я либо явно протестировал бы для if postedcountry is not None: ..., либо я бы поставил вашему .get() (необязательное) значение по умолчанию для "postscountry".

Как вы хотите справиться с ситуацией, когда у request не было postscountry ? Вы хотите предположить, что это отправлено от некоторого определенного по умолчанию? Принудительно перенаправить на некоторую страницу, которая требует от пользователя предоставить значение для этого элемента формы? Оповещение испанской инквизиции?

1 голос
/ 22 августа 2009

Вы пытаетесь установить строку в ReferenceProperty. Поле 'country' в CMSCountry является db.ReferenceProperty, которое принимает объект db.Key или CMSCountry, но вы пытаетесь установить его в строку.

Вы должны делать что-то вроде этого:

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)

Пожалуйста, сообщите об ошибке относительно довольно бесполезного сообщения об ошибке.

1 голос
/ 22 августа 2009

Если вы прочитаете трассировку, она точно скажет вам, что происходит:

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

Это говорит о том, что используемая вами переменная value не имеет атрибута has_key. И это говорит вам о том, что ваша переменная value не является словарем, так как похоже, что вы ожидаете ... вместо этого это объект Unicode, который в основном является строкой.

0 голосов
/ 08 октября 2010

Метод объекта словаря has_key () устарел в 3.0 - используйте вместо него выражение "in". Если вы используете старую библиотеку в 3.x, вы должны внести изменения в код для ее адаптации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...