Updating selection data in DictSchema

I walk into a weird problem when updating the selection data in a DictSchema through a wizard. I have a class:

class WebApiReferenceInformation(DictSchemaMixin, ModelSQL, ModelView):
    "API Reference Information"
    __name__ = 'webapi.api.reference.information'

Because of the DictSchema several columns are added to the database table. Using the wizard I want to change a existing record, or if it doesn’t exist create that record. Adding new records is not a problem. Updating different data is not a problem.

However when I have a record which is has a type_ of Selection the data in the column selection cannot be updated. All other columns of that record can be updated like selection_sorted or name.

I don’t get an error or warning it just doesn’t do it.

You will have to debug. What are the data you are saving?

I’m searching if the record exists and based on that, update or create a new record.

pool = Pool()
Information = pool.get('webapi.api.reference.information')

information = Information.search([('name', '=', name)])

if information:
    Information.write(information, {'selection': '1:Hello World'})
else:
    Information.create(.....)

Debugging shows that there is something going on in the backend which removes the fields from the query. Below are the database queries.

DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" FROM "webapi_api_reference_information" AS "a" WHERE (("a"."id" IN (83)))'
----> DEBUG trytond.backend.postgresql.database b'UPDATE "webapi_api_reference_information" AS "a" SET "write_uid" = 6, "write_date" = CURRENT_TIMESTAMP WHERE (("a"."id" IN (83)))'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" AS "id", "a"."create_date" AS "create_date", "a"."create_uid" AS "create_uid", "a"."fuzzy" AS "fuzzy", "a"."lang" AS "lang", "a"."module" AS "module", "a"."name" AS "name", "a"."overriding_module" AS "overriding_module", "a"."res_id" AS "res_id", "a"."src" AS "src", "a"."type" AS "type", "a"."value" AS "value", "a"."write_date" AS "write_date", "a"."write_uid" AS "write_uid", CAST(EXTRACT(\'EPOCH\' FROM COALESCE("a"."write_date", "a"."create_date")) AS VARCHAR) AS "_timestamp" FROM "ir_translation" AS "a" WHERE (("a"."lang" = \'nl\') AND ("a"."type" = \'model\') AND ("a"."name" = \'webapi.api.reference.information,selection\') AND ("a"."res_id" IN (83))) ORDER BY "a"."id" ASC'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."write_date" AS "write_date", "a"."selection" AS "selection", "a"."id" AS "id" FROM "webapi_api_reference_information" AS "a" WHERE (("a"."id" IN (83)))'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" AS "id", "a"."create_date" AS "create_date", "a"."create_uid" AS "create_uid", "a"."fuzzy" AS "fuzzy", "a"."lang" AS "lang", "a"."module" AS "module", "a"."name" AS "name", "a"."overriding_module" AS "overriding_module", "a"."res_id" AS "res_id", "a"."src" AS "src", "a"."type" AS "type", "a"."value" AS "value", "a"."write_date" AS "write_date", "a"."write_uid" AS "write_uid", CAST(EXTRACT(\'EPOCH\' FROM COALESCE("a"."write_date", "a"."create_date")) AS VARCHAR) AS "_timestamp" FROM "ir_translation" AS "a" WHERE (("a"."lang" = \'en\') AND ("a"."type" = \'model\') AND ("a"."name" = \'webapi.api.reference.information,selection\') AND ("a"."value" != \'\') AND ("a"."value" IS NOT NULL) AND ("a"."res_id" IN (83)) AND (("a"."fuzzy" = false) OR ("a"."fuzzy" IS NULL))) ORDER BY "a"."id" ASC'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" FROM "ir_translation" AS "a" WHERE (("a"."id" IN (90734)))'
----> DEBUG trytond.backend.postgresql.database b'UPDATE "ir_translation" AS "a" SET "write_uid" = 6, "write_date" = CURRENT_TIMESTAMP, "src" =\'1:Hello World\', "value" = NULL, "fuzzy" = false WHERE (("a"."id" IN (90734)))'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."name" AS "name", "a"."write_uid" AS "write_uid", "a"."src" AS "src", "a"."overriding_module" AS "overriding_module", "a"."write_date" AS "write_date", "a"."id" AS "id", "a"."create_date" AS "create_date", "a"."lang" AS "lang", "a"."module" AS "module", "a"."res_id" AS "res_id", "a"."value" AS "value", "a"."fuzzy" AS "fuzzy", "a"."create_uid" AS "create_uid", "a"."type" AS "type" FROM "ir_translation" AS "a" WHERE (("a"."id" IN (90734)))'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."write_date" AS "write_date", "a"."selection" AS "selection", "a"."id" AS "id" FROM "webapi_api_reference_information" AS "a" WHERE (("a"."id" IN (83)))'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" AS "id", "a"."create_date" AS "create_date", "a"."create_uid" AS "create_uid", "a"."fuzzy" AS "fuzzy", "a"."lang" AS "lang", "a"."module" AS "module", "a"."name" AS "name", "a"."overriding_module" AS "overriding_module", "a"."res_id" AS "res_id", "a"."src" AS "src", "a"."type" AS "type", "a"."value" AS "value", "a"."write_date" AS "write_date", "a"."write_uid" AS "write_uid", CAST(EXTRACT(\'EPOCH\' FROM COALESCE("a"."write_date", "a"."create_date")) AS VARCHAR) AS "_timestamp" FROM "ir_translation" AS "a" WHERE (("a"."lang" = \'nl\') AND ("a"."type" = \'model\') AND ("a"."name" = \'webapi.api.reference.information,selection\') AND ("a"."value" != \'\') AND ("a"."value" IS NOT NULL) AND ("a"."res_id" IN (83)) AND (("a"."fuzzy" = false) OR ("a"."fuzzy" IS NULL))) ORDER BY "a"."id" ASC'
DEBUG trytond.backend.postgresql.database b'SELECT "a"."id" FROM "ir_session_wizard" AS "a" WHERE (("a"."id" IN (69149)))'
.....

In the first update query the selection data is missing. Using for example selection_sorted the query looks like:

DEBUG trytond.backend.postgresql.database b'UPDATE "webapi_api_reference_information" AS "a" SET "write_uid" = 6, "write_date" = CURRENT_TIMESTAMP, "selection_sorted" = true WHERE (("a"."id" IN (83)))'

I also discovered that changing the string also cannot be updated, but the translations does.

This is a translated field so you must update for all the languages.
Indeed I guess you are writing with a contextual language that is not the default language of Tryton. That’s why the column in the main table is not updated.
After that I do not know why the value is not stored in the translation but only the source.

Indeed trying to simulate the form behavior in a wizard is a very hard work most of the time.
Use the form, Luke :wink:

In this case that isn’t possible :cry:. The wizard will fetch the data from a website API, does some operations on it and then pushes it into the database. The user cannot do much about it.

Indeed I’m not using the default language of Tryton. Moving the query into a new Transaction with the default Tryton language fixes it. I can now change the data on the website and then execute the wizard which updates the data correctly.

So to make it complete:

with Transaction().set_context({'language': 'en'}):
    pool = Pool()
    Information = pool.get('webapi.api.reference.information')

    information = Information.search([('name', '=', name)])

    if information:
        Information.write(information, {'selection': <selection_data>})
    else:
        Information.create(.....)