Проблема с методом получения? AttributeError Жалоба на объект 'str'

Проблема: AttributeError: 'str' object has no attribute '_sa_instance_state' и я не знаю, как это исправить. Я считаю, что это связано с методами retrieve ниже. У кого-то в Stacks была аналогичная проблема, и это было простой вопрос изменения функции... для меня это не так.

Отслеживание:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/ack/code/venv/NotssDB/notssdb/test/test.py", line 132, in test1
    api.retrieve_assessment_result('baseball', 'Becoming a Leader')
  File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 324, in retrieve_assessment_result
    filter(Assessment_Result.owner == owner).one()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/operators.py", line 301, in __eq__
    return self.operate(eq, other)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 175, in operate
    return op(self.comparator, *other, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1011, in __eq__
    other, adapt_source=self.adapter))
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1338, in _optimized_compare
    state = attributes.instance_state(state)
AttributeError: 'str' object has no attribute '_sa_instance_state'

объект.py

def retrieve_assessment_result(self, *args):
    id, owner, assessment = None, None, None
    if len(args) == 1:
        id, = args[0]
    elif len(args) == 2:
        owner, assessment = args
    else:
        raise ValueError('Value being passed is an object')
    if id is not None:
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.id == id).one()
    elif owner is not None:
        print 'test1', owner
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.owner == owner).one()
    elif assessment is not None:
        print 'test2', assessment
        return self.session.query(Assessment_Result).\
        filter(Assessment_Result.assessment == assessment).one()

def create_category_rating(self, category_rating_int, category, assessment_result):
    new_catrating = Category_Rating(category_rating_int, category, assessment_result)
    self.session.add(new_catrating)
    print(new_catrating)
    self.session.commit()
    return(new_catrating)

удобство.py (наследуется от object.py)

def create_category_rating(self, category_rating_int, category_name, username, name):
    category = self.retrieve_category(category_name)
    owner = self.retrieve_user(username)  
    assessment = self.retrieve_assessment(name)  
    assessment_result = self.retrieve_assessment_result(owner, assessment)
    return super(ConvenienceAPI, self).create_category_rating(category_rating_int, category, assessment_result)

модель.py

class Category_Rating(Base):
    __tablename__ = 'category_ratings'

    id = Column(Integer, primary_key=True)
    category_rating_int = Column(Integer)

    category_id = Column(Integer, ForeignKey('categories.category_id'))
    category = relationship('Category', backref='category_ratings')

    assessment_result_id = Column(Integer, ForeignKey('assessment_results.id'))
    assessment_result = relationship('Assessment_Result', backref='category_ratings')

    def __init__(self, category_rating_int, category, assessment_result): #OBJECT
        self.category_rating_int = category_rating_int
        self.category = category
        self.assessment_result  = assessment_result

    def __repr__(self):
        return "<Category_Rating(category_rating_int='%s')>" % (self.category_rating_int)

test.py

api = ConvenienceAPI()
api.create_category_rating(2, 'Decision-Making', 'baseball', 'Becoming a Leader')

person thesayhey    schedule 02.10.2015    source источник
comment
Пожалуйста, включите минимальный, полный, поддающийся проверке пример, включая определение вашей модели. Чтобы люди могли воспроизвести вашу ошибку. Также включите значения, которые вы передаете в качестве параметров при вызове create_category_rating(...).   -  person Yaroslav Admin    schedule 02.10.2015
comment
Вы прочитали объяснение из связанного вопроса? Проблема не в изменении функции. Это ясно объясняет, в чем проблема: вы назначаете список отношениям, где uselist=False. Вы должны установить один экземпляр модели, а не список, содержащий его. Скорее всего, вы делаете то же самое, когда создаете экземпляр Category_Rating.   -  person Yaroslav Admin    schedule 02.10.2015
comment
@YaroslavAdmin Да, есть. Я разместил запрошенный материал сейчас. Я борюсь с пониманием своего собственного, поскольку я новичок во всем этом.   -  person thesayhey    schedule 02.10.2015


Ответы (2)


Ваша проблема точно такая же, как и в связанном вопросе:

Вы назначаете список отношениям, где uselist=False. Вы должны установить один экземпляр модели, а не список, содержащий его.

В вашем случае свойство assessment_results определяется как отношение "многие к одному" (например, один Category_Rating может иметь один экземпляр Assessment_Results, а один Assessment_Results может иметь несколько экземпляров Category_Rating). Если вы сделаете следующие переименования, предыдущие операторы будут иметь для вас гораздо больше смысла:

assessment_results -> assessment_result
assessment_results_id -> assessment_result_id
Assessment_Results -> Assessment_Result

Проблема в том, что свойство assessment_results ожидает один экземпляр модели Assessment_Results, но вы устанавливаете его как результат метода retrieve_assessment_results(), который возвращает список Assessment_Results. Вот почему это не удается.

UPD

Вторая проблема в этой строке filter(Assessment_Result.owner == owner).one(). Вы пытаетесь сравнить экземпляр Owner со строкой. Вероятно, вы захотите заменить его чем-то вроде filter(Owner.name == owner).one(). Не могу сказать вам точно, не видя определения этих моделей.

person Yaroslav Admin    schedule 02.10.2015
comment
Ваше объяснение высоко ценится! Спасибо. Просто для уточнения: Assessment_Results — это таблица для хранения каждого Assessment и соответствующих им categories. Таким образом, Assessment_Results будет содержать около 4 category_ratings на Assessment_Results . - person thesayhey; 02.10.2015
comment
Чем мое предположение неверно. Вам не нужно перемещать определение отношений в модель Assessment_Results. Просто убедитесь, что вы возвращаете одиночный экземпляр из метода retrieve_assessment_results(). Используйте .one() или < a href="http://docs.sqlalchemy.org/en/relAssessment_Results0/orm/query.html#sqlalchemy.orm.query.Query.first" rel="nofollow noreferrer">.first() вместо .all() в зависимости от в вашей структуре данных. - person Yaroslav Admin; 02.10.2015
comment
Я изменил соглашение об именах (во избежание недоразумений), так что спасибо за это! Когда я передаю .one(), он возвращает AttributeError: 'str' object has no attribute '_sa_instance_state' Итак, я могу обновить свой вопрос, чтобы более точно отразить это с помощью Traceback в соответствии с вашим предложением? - person thesayhey; 02.10.2015
comment
Хорошо, обновите вопрос новым кодом и добавьте новую трассировку. Или вы можете отладить его самостоятельно. Скорее всего, вы присваиваете отношениям строку вместо модели. - person Yaroslav Admin; 02.10.2015

Работая с Ярославом Админом, я сделал что-то похожее на его предложение... Я добавил метод получения для assessment_result(..) в файле comfort.py (api), который будет проверять наличие строк:

рабочий код:
(наследуется от файла object.py, показанного выше)

def retrieve_assessment_result(self, username, name):
    owner = self.retrieve_user(username)
    assessment = self.retrieve_assessment(name)
    return super(ConvenienceAPI, self).retrieve_assessment_result(owner, assessment)
person thesayhey    schedule 02.10.2015