ValueError: Ожидаемый синглтон: res.partner(1, 12, 29, 30, 36) — res.partner — сообщество Odoo v10

Я унаследовал модель res.partner, это переход от сообщества v8 к v10.

Методы нарушения выглядят следующим образом:

@api.depends('company_id')
def _get_country_code(self):
    """
    Return the country code of the user company. If not exists, return XX.
    """
    #context = dict(self._context or {})
    for partner in self:
        user_company = self.env['res.company'].browse(self.company_id)
        #NOTE: replace code name with your real field name where you want to see value 
        partner.code = user_company.partner_id and user_company.partner_id.country_id \
            and user_company.partner_id.country_id.code or 'XX'

@api.multi
def _get_uid_country(self): 
    """ Return a dictionary of key ids as invoices, and value the country code
    of the user company.
    """
    res = {}.fromkeys(self._get_country_code()) 
    return res

Теперь каждый раз, когда я нажимаю на клиента или поставщика (res.partner), он выдает мне это:

Traceback (most recent call last):
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 638, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 675, in dispatch
result = self._call_function(**self.params)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 331, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/service/model.py", line 119, in wrapper
return f(dbname, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 324, in checked_call
result = self.endpoint(*a, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 933, in __call__
return self.method(*args, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 504, in response_wrap
response = f(*args, **kw)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 862, in call_kw
return self._call_kw(model, method, args, kwargs)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 854, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 681, in call_kw
return call_kw_multi(method, model, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 672, in call_kw_multi
result = method(recs, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 2995, in read
values[name] = field.convert_to_read(record[name], record, use_name_get)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 5171, in __getitem__
return self._fields[key].__get__(self, type(self))
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 860, in __get__
self.determine_value(record)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 969, in determine_value
self.compute_value(recs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 924, in compute_value
self._compute_value(records)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 916, in _compute_value
getattr(records, self.compute)()
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/model/partner.py", line 90, in _get_uid_country
res = {}.fromkeys(self._get_country_code()) #ids, cr, uid, context=context)
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/model/partner.py", line 68, in _get_country_code
user_company = self.env['res.company'].browse(self.company_id)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 854, in __get__
record.ensure_one()
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 4783, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.partner(1, 33, 8, 18, 22, 23)

Я думаю, что это связано с этой строкой user_company = self.env['res.company'].browse(self.company_id), но я не уверен на 100%.

Любые идеи?

ИЗМЕНИТЬ

Оригинальные методы старого API:

def _get_country_code(self, cr, uid, context=None):
    """
    Return the country code of the user company. If not exists, return XX.
    """
    context = context or {}
    user_company = self.pool.get('res.users').browse(
        cr, uid, uid, context=context).company_id
    return user_company.partner_id and user_company.partner_id.country_id \
        and user_company.partner_id.country_id.code or 'XX'

def _get_uid_country(self, cr, uid, ids, field_name, args, context=None):
    """ Return a dictionary of key ids as invoices, and value the country code
    of the user company.
    """
    context = context or {}
    res = {}.fromkeys(ids, self._get_country_code(cr, uid,
                                                  context=context))
    return res

person NeoVe    schedule 20.03.2017    source источник
comment
Трудно понять требования. Вы работаете в партнерах, но говорите о пользовательской компании. Каковы требования для этого метода вычислений?   -  person CZoellner    schedule 20.03.2017
comment
И не могли бы вы также добавить старые методы в стиле API?   -  person CZoellner    schedule 20.03.2017
comment
Привет @CZoellner, да, этот модуль был создан не мной, лол, я просто переношу его из локализации.   -  person NeoVe    schedule 20.03.2017
comment
Привет, отредактировал мой вопрос с оригинальными старыми функциями API, пожалуйста, посмотрите, спасибо!   -  person NeoVe    schedule 20.03.2017


Ответы (4)


Я попытался немного сократить:

uid_country = fields.Char(
    string="Country Code of Current User",
    compute="_get_uid_country")

@api.multi
@api.depends('company_id')  # there should be a better trigger field
def _get_uid_country(self):
    """ Compute country code by current users company """
    country_code = self.env.user.company_id.partner_id.country_id.code or 'XX'
    for partner in self:
        partner.update({'uid_country': country_code})

Этого должно быть достаточно. Мне кажется, что реального триггерного поля нет, а вычисляемое поле будет вычисляться каждый раз при вызове партнера. Но это должно работать.

person CZoellner    schedule 20.03.2017
comment
Большое спасибо, выдает это: return self._fields[key].__set__(self, value) KeyError: 'code', хммм, это в этой строке 'partner.update({'code': country_code})' хммм - person NeoVe; 20.03.2017
comment
Должен ли я открыть новый вопрос для этого? - person NeoVe; 20.03.2017
comment
Нет, я использовал code, потому что вы тоже его использовали. Я не знаю имя вычисляемого поля. Может быть, вы можете сказать мне, тогда я обновлю свой ответ. - person CZoellner; 20.03.2017
comment
Привет, спасибо, так как это сделано не мной, я думаю, что это поле «uid_country», я пытался с этим, но он говорит: «Объект NoneType не является итерируемым», :/ - person NeoVe; 20.03.2017
comment
res = {}.fromkeys(self._get_country_code()) TypeError: объект 'NoneType' не является итерируемым - person NeoVe; 20.03.2017
comment
откуда вы взяли res = {}.fromkeys(self._get_country_code())? Этого нет в моем ответе. - person CZoellner; 20.03.2017
comment
Да, я знаю, но это код, который вызывает _get_country_code, он присутствует в моем вопросе - person NeoVe; 20.03.2017
comment
Вам просто нужен мой код, ничего больше, кроме определения поля, которое я сейчас отредактирую. - person CZoellner; 20.03.2017
comment
Круто, так что в uid_country, который вычисляет функцию, которая вызывает функцию _get_uid_country, мне нужно изменить атрибут 'compute=' на вашу функцию, хорошо, попробую, извините, в этих модулях есть кое-что странное: / - person NeoVe; 20.03.2017
comment
Исходный код показывает _get_uid_country как функцию вычисления, вы можете увидеть это в параметрах. - person CZoellner; 20.03.2017
comment
Да ну, я поставил _get_country_code, сейчас поменяю, но результат тот же :) , Большое спасибо xD, отлично работает! Прост - person NeoVe; 20.03.2017

Вы можете попробовать заменить эту строку:

user_company = self.env['res.company'].browse(self.company_id)

с этим

user_company = self.env['res.company'].browse(partner.company_id)

а потом дайте нам знать

person Walid Mashal    schedule 20.03.2017
comment
Привет, пишет "ProgrammingError: не удается адаптировать тип "res.company" :/ - person NeoVe; 20.03.2017
comment
Я отредактировал свой вопрос, используя оригинальные старые методы API, спасибо. - person NeoVe; 20.03.2017
comment
Попробуйте это: user_company = self.env['res.company'].browse(partner.company_id.id) - person Walid Mashal; 20.03.2017

Когда вы используете @api.multi self, это RecordSet :

RecordSet может иметь 0 или 1 или более записей, когда вы используете self.getSomeThing, это работает, если RecordSet имеет одну запись, но если у него более одной, возникает исключение, потому что он не будет знать запись ведьмы, которую вы хотите спросить. поэтому, если вы используете @api.multi, старайтесь всегда зацикливать набор записей. @api.depends также похож на @api.multi, что self является набором записей.

for rec in self :
     rec.getSomeThing

или используйте @api.one здесь self всегда является одной записью, но не рекомендуется, потому что он вызывает getSomeThing в соответствии с количеством записей в вашем представлении, поэтому для представления формы это не проблема, потому что у него есть только один, но для древовидного представления вы можете себе представить.

person Charif DZ    schedule 20.03.2017

Вы должны попробовать функцию _get_uid_country как:

for record in self.browse(): result = {}.fromkeys(record._get_country_code(), False)

person Hilar AK    schedule 20.03.2017
comment
Я вижу цель этого ответа, но поскольку целевой платформой является odoo 10, здесь есть две вещи (возможно, предположения), которые просто неверны. Сначала self представляет собой RecordSet со всеми необходимыми записями базы данных уже в виде экземпляров python. Здесь не нужно ничего просматривать. И, во-вторых, больше нет необходимости что-либо возвращать в вычислительных методах odoo 10. Но я признаю, что трудно реализовать _get_uid_country как метод вычисления. - person CZoellner; 20.03.2017
comment
@CZoellner Спасибо за информацию. - person Hilar AK; 21.03.2017