Как сделать поле Inputable на основе условия в ODOO 10?

Вы должны быть в состоянии безопасно объединить asyncio и multiprocessing без особых проблем, хотя вы не должны использовать multiprocessing напрямую. Кардинальный грех asyncio (и любой другой асинхронной структуры на основе цикла событий) блокирует цикл события. Если вы попытаетесь напрямую использовать multiprocessing, каждый раз, когда вы блокируете дождевой процесс, вы собираетесь заблокировать цикл событий. Очевидно, что это плохо.

Самый простой способ избежать этого - использовать BaseEventLoop.run_in_executor для выполнения функции в concurrent.futures.ProcessPoolExecutor . ProcessPoolExecutor - пул процессов, реализованный с использованием multiprocessing.Process, но asyncio имеет встроенную поддержку для выполнения в нем функции без блокировки цикла события. Вот простой пример:

import time
import asyncio
from concurrent.futures import ProcessPoolExecutor

def blocking_func(x):
   time.sleep(x) # Pretend this is expensive calculations
   return x * 5

@asyncio.coroutine
def main():
    #pool = multiprocessing.Pool()
    #out = pool.apply(blocking_func, args=(10,)) # This blocks the event loop.
    executor = ProcessPoolExecutor()
    out = yield from loop.run_in_executor(executor, blocking_func, 10)  # This does not
    print(out)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Для большинства случаев эта функция сама по себе достаточно хороша. Если вам понадобятся другие конструкции из multiprocessing, например Queue, Event, Manager и т. Д., Существует сторонняя библиотека, называемая aioprocessing (полное раскрытие: Я написал это), который предоставляет asyncio -совместимые версии всех структур данных multiprocessing. Вот пример демонстрации того, что:

import time
import asyncio
import aioprocessing
import multiprocessing

def func(queue, event, lock, items):
    with lock:
        event.set()
        for item in items:
            time.sleep(3)
            queue.put(item+5)
    queue.close()

@asyncio.coroutine
def example(queue, event, lock):
    l = [1,2,3,4,5]
    p = aioprocessing.AioProcess(target=func, args=(queue, event, lock, l)) 
    p.start()
    while True:
        result = yield from queue.coro_get()
        if result is None:
            break
        print("Got result {}".format(result))
    yield from p.coro_join()

@asyncio.coroutine
def example2(queue, event, lock):
    yield from event.coro_wait()
    with (yield from lock):
        yield from queue.coro_put(78)
        yield from queue.coro_put(None) # Shut down the worker

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    queue = aioprocessing.AioQueue()
    lock = aioprocessing.AioLock()
    event = aioprocessing.AioEvent()
    tasks = [ 
        asyncio.async(example(queue, event, lock)),
        asyncio.async(example2(queue, event, lock)),
    ]   
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()

1
задан CZoellner 4 March 2019 в 08:50
поделиться

1 ответ

Поле compute в odoo по умолчанию readonly=True и store=False. Вы можете установить store=True, просто передав его в определение поля, но чтобы сделать поле compute доступным / не только для чтения, вы должны передать inverse в определении поля, которое является строковым значением, именем функции то есть, когда значение поля вычислений устанавливается вручную. Идея состоит в том, чтобы вычислить значение depends для поля, упомянутого в @api.depends, декоратор. Поэтому, если вы устанавливаете значение поля compute с помощью ручного ввода, то вам может понадобиться функция inverse, которая соответственно установит соответствующее поле depends.

field_a = fields.Char("Field A")
field_b = fields.Char("Field B", compute="_compute_field_b", inverse="_set_field_b")
field_selection = fields.Selection([('choice_a', "Choice A"), ('choice_b', "Choice B")]) 

@api.multi 
@api.depends('field_selection, field_a')
def _compute_field_b(self):
    for res in self:
        if res.selection_choice == 'choice_a':
            res.field_b = res.field_a
        else:
            res.field_b = ""

@api.multi
def _set_field_b(self):
    for res in self:
         if res.field_selection == 'choice_a':
            res.field_a = res.field_b

Если вам не нужны какие-либо функции inverse при установке значения возврата, вы можете просто return True ничего не делать. Это сделает вычислительное поле редактируемым.

0
ответ дан arryph 4 March 2019 в 08:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: