Модель для взаимодействия с внешним источником данных в Odoo

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

После небольших изысканий решение было найдено и им я бы хотел поделиться.

Опредение методов для переопределения

Первым шагом я выяснил какой метод отвечает за вывод данных в интерфейс.

Для этого я посмотрел в консоли браузера какой метод вызывается в момент запроса:

демо

Данным методом оказался search_read.

Класс для работы с redis

Для взаимодействия с Redis нужно добавить параметры соединения в конфигурационный файл, а для операций определим новый класс:

from odoo.tools.config import config
import json
import redis

redis_engine = redis.Redis(host=config.get('redis'), db=0)

class RedisModel(object):
    @api.model
    def search_read(self, domain=None, fields=None, offset=0, limit=0, order=None):
        data = [json.loads(redis_engine.lindex('odoo', i)) for i in range(0, redis_engine.llen('odoo'))] 
        if domain:
            out = []
            for key, cond, val in domain:
                    if cond == '=':
                        out.extend([row for row in data if row.get(key) == val])
            
            data = out
        return data

    @api.model
    def search_count(self, args):
        return redis_engine.llen('odoo')

Как видно в данном примере бы переопределен метод для вывода данных в интерфейс и метод подсчета общего кол-ва строк.

Кроме того в search_read проверяется наличие условия для поиска значения в Redis.

Mixin для модели

Теперь необходимо создать модель, которая будет наследоваться от нашей Redis модели и от модели Odoo

class Points(RedisModel, models.Model):
    _name = "points"
    
    client = fields.Integer("Client")
    packet_id = fields.Integer("Packet id")
    lat = fields.Float("Latitude")
    lon = fields.Float("Longitude")

Из-за особенностей MRO в Python класс для взаимодействия с Redis должен идти первым.

Вывод

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

демо

 
comments powered by Disqus