TypeError:“方法”对象不可下标Python / django

时间:2019-12-03 05:34:19

标签: django python-3.x dictionary

我有一个返回以下错误的测试用例。

跟踪

Traceback (most recent call last):
  File "/usr/lib/python3.7/unittest/mock.py", line 1255, in patched
    return func(*args, **keywargs)
  File "/dir/to/project/Anwser/qanda/tests.py", line 29, in test_elasticsearch_upsert_on_save
    q.save()
  File "/dir/to/project/Anwser/qanda/models.py", line 40, in save
    elasticsearch.upsert(self)
  File "/dir/to/project/Anwser/qanda/service/elasticsearch.py", line 54, in upsert
    doc_type = question_dict['_type']
TypeError: 'method' object is not subscriptable

这是elasticsearch.py内的函数

def upsert(question_model):
    client = get_client()
    question_dict = question_model.as_elastic_search_dict
    doc_type = question_dict['_type']
    del question_dict['_id']
    del question_dict['_type']
    response = client.update(
        settings.ES_IDENX,
        question_dict,
        id=question_model.id,
        body={
            'doc': doc_type,
            'doc_as_upsert': True,
        }
    )
    return response

当我阅读了有关类似问题的其他文章时,我得出的结论是,问题取决于调用该函数的对象的 __ getItem(self)__ 。 由于该函数应该返回字典,因此它返回一个方法。

这是模型内部的功能。

def as_elastic_search_dict(self):
        return {
            '_id': self.id,
            '_type': 'doc',
            'text': '{}\n{}'.format(self.title, self.question),
            'question_body': self.question,
            'title': self.title,
            'id': self.id,
            'created': self.created,
        }

TestCase:

class QuestionSaveTestCase(TestCase):
    """
        Testing Question.save()
    """

    @patch('qanda.service.elasticsearch.Elasticsearch')
    def test_elasticsearch_upsert_on_save(self, ElasticSearchMock):
        user = User.objects.create(
            username='unittest',
            password='unittest'
        )
        question_title = 'Unit test'
        question_body = 'Some unit test'
        q = Question(title=question_title,
                     question=question_body,
                     user=user)
        q.save()

        self.assertIsNotNone(q.id)
        self.assertTrue(ElasticSearchMock.called)
        mock_client = ElasticSearchMock.return_value
        mock_client.update.assert_called_once_with(
            settings.ES_IDENX,
            id=q.id,
            body={
                'doc': {
                    '_type': 'doc',
                    'text': '{}\n{}'.format(question_title, question_body),
                    'question_body': question_body,
                    'title': question_title,
                    'id': q.id,
                    'created': q.created,
                },
                'doc_as_upsert': True,
            }
        )

可用于解决此问题的所有可能用例是什么?如果我的理解是正确的,那么我应该重写 __ getItem(self)__ 以返回字典。如果正确,我应该如何实现 __ getItem(self)__ ,并且将其配置为返回字典,它将对对象的生命周期产生总体影响?

1 个答案:

答案 0 :(得分:0)

您需要执行该方法,方法名称后缺少括号,将question_model.as_elastic_search_dict更改为question_model.as_elastic_search_dict()

所以您的功能将是:

def upsert(question_model):
    client = get_client()
    question_dict = question_model.as_elastic_search_dict()
    doc_type = question_dict['_type']
    del question_dict['_id']
    del question_dict['_type']
    response = client.update(
        settings.ES_IDENX,
        question_dict,
        id=question_model.id,
        body={
            'doc': doc_type,
            'doc_as_upsert': True,
        }
    )
    return response