Как стать автором
Обновить

Рецепты REST OData в 1C: Python vs… PL/pgSQL !?

Время на прочтение8 мин
Количество просмотров6K

Для приготовления CRUD нам понадобится 1C, Python и ... PostgreSQL. Сначала нужно включить REST OData в 1C.

Поиск будем осуществлять следующей функцией на Python

import requests # импортируем библиотеку
def filter( # определяем функцию
    entity, # имя сущности
    filter=None, # фильтр для поиска сущности
    select=None, # выбор только заданных полей сущности
):
    url = f'http(s)://1c.host.name/api/odata/standard.odata/{entity}' # конструируем адрес
    headers = dict(Accept='application/json') # задаём тип ответа
    params = dict() # объявляем параметры
    if filter is not None: params['$filter'] = filter # если задан фильтр, то задаём его
    if select is not None: params['$select'] = select # если задан выбор полей, то задаём его
    response = requests.get(url, headers=headers, params=params) # выполняем запрос
    try: json = response.json() # получаем результат и пытаемся преобразовать его в json
    except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
    if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
    return json['value'] # возвращаем массив сущностей

и на ... PL/pgSQL с помощью расширения pg_curl

create or replace function filter( -- создаём или меняем функцию
    entity text, -- имя сущности
    filter text default null, -- фильтр для поиска сущности
    "select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
    url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s?$$, curl_easy_escape(entity)); -- объявляем и конструируем адрес
    jsonb jsonb; -- объявляем возвращаемую переменную
    text text; -- и вспомогательную переменную
begin
    perform curl_easy_setopt_url(url); -- задаём адрес
    perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
    if filter is not null then perform curl_url_append('$filter', filter); end if; -- если задан фильтр, то задаём его
    if "select" is not null then perform curl_url_append('$select', "select"); end if; -- если задан выбор полей, то задаём его
    perform curl_easy_perform(); -- выполняем запрос
    text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
    begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
    if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
    return nullif(jsonb->'value', '[]'); -- возвращаем непустой массив сущностей или ничего
end;$body$;    

Чтение будем осуществлять следующей функцией на Python

import requests # импортируем библиотеку
def read( # определяем функцию
    entity, # имя сущности
    guid, # идентификатор сущности
    select=None, # выбор только заданных полей сущности
):
    url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
    headers = dict(Accept='application/json') # задаём тип ответа
    params = dict() # объявляем параметры
    if select is not None: params['$select'] = select # если задан выбор полей, то задаём его
    response = requests.get(url, headers=headers, params=params) # выполняем запрос
    try: json = response.json() # получаем результат и пытаемся преобразовать его в json
    except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
    if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
    return json # возвращаем сущность

и на ... PL/pgSQL

create or replace function read( -- создаём или меняем функцию
    entity text, -- имя сущности
    guid uuid, -- идентификатор сущности
    "select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
    url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
    jsonb jsonb; -- объявляем возвращаемую переменную
    text text; -- и вспомогательную переменную
begin
    perform curl_easy_setopt_url(url); -- задаём адрес
    perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
    if "select" is not null then perform curl_url_append('$select', "select"); end if; -- если задан выбор полей, то задаём его
    perform curl_easy_perform(); -- выполняем запрос
    text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
    begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
    if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
    return jsonb; -- возвращаем сущность
end;$body$;

Создание будем осуществлять следующей функцией на Python

import requests # импортируем библиотеку
def create( # определяем функцию
    entity, # имя сущности
    data, # тело сущности
    select=None, # выбор только заданных полей сущности
):
    url = f'http(s)://1c.host.name/api/odata/standard.odata/{entity}' # конструируем адрес
    headers = dict(Accept='application/json') # задаём тип ответа
    response = requests.post(url, headers=headers, data=data) # выполняем запрос
    try: json = response.json() # получаем результат и пытаемся преобразовать его в json
    except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
    if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
    if select is not None: return read(entity, json['Ref_Key'], select) # если задан выбор полей, то заново читаем и возвращаем сущность
    return json # иначе просто возвращаем сущность

и на ... PL/pgSQL

create or replace function "create"( -- создаём или меняем функцию
    entity text, -- имя сущности
    jsonb jsonb, -- тело сущности
    "select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
    url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s?$$, curl_easy_escape(entity)); -- объявляем и конструируем адрес
    text text; -- объявляем вспомогательную переменную
begin
    perform curl_easy_setopt_postfields(convert_to(jsonb::text, 'utf-8')); -- задаём тело
    perform curl_easy_setopt_url(url); -- задаём адрес
    perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
    perform curl_easy_perform(); -- выполняем запрос
    text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
    begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
    if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
    if "select" is not null then return read(entity, (jsonb->>'Ref_Key')::uuid, "select"); end if; -- если задан выбор полей, то заново читаем и возвращаем сущность
    return jsonb; -- иначе просто возвращаем сущность
end;$body$;

Удаление будем осуществлять следующей функцией на Python

import requests # импортируем библиотеку
def delete( # определяем функцию
    entity, # имя сущности
    guid, # идентификатор сущности
):
    url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
    headers = dict(Accept='application/json') # задаём тип ответа
    response = requests.delete(url, headers=headers) # выполняем запрос
    try: json = response.json() # получаем результат и пытаемся преобразовать его в json
    except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
    if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение

и на ... PL/pgSQL

create or replace function delete( -- создаём или меняем функцию
    entity text, -- имя сущности
    guid uuid -- идентификатор сущности
) returns void language plpgsql as $body$ declare -- ничего не возвращающую на языке PL/pgSQL
    url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
    jsonb jsonb; -- объявляем вспомогательную переменную
    text text; -- и ещё одну
begin
    perform curl_easy_setopt_customrequest('DELETE'); -- задаём тип запроса
    perform curl_easy_setopt_url(url); -- задаём адрес
    perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
    perform curl_easy_perform(); -- выполняем запрос
    text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
    begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
    if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
end;$body$;

Обновление будем осуществлять следующей функцией на Python

import requests # импортируем библиотеку
def update( # определяем функцию
    entity, # имя сущности
    guid, # идентификатор сущности
    data, # тело сущности
    select=None, # выбор только заданных полей сущности
):
    url = f'''http(s)://1c.host.name/api/odata/standard.odata/{entity}(guid'{guid}')''' # конструируем адрес
    headers = dict(Accept='application/json') # задаём тип ответа
    response = requests.patch(url, headers=headers, data=data) # выполняем запрос
    try: json = response.json() # получаем результат и пытаемся преобразовать его в json
    except: raise Exception(response.text) # а в случае неудачи поднимаем исключение
    if 'odata.error' in json: raise Exception(json['odata.error']['message']['value']) # если в результате ошибка, то поднимаем исключение
    if select is not None: return read(entity, json['Ref_Key'], select) # если задан выбор полей, то заново читаем и возвращаем сущность
    return json # иначе просто возвращаем сущность

и на ... PL/pgSQL

create or replace function update( -- создаём или меняем функцию
    entity text, -- имя сущности
    guid uuid, -- идентификатор сущности
    jsonb jsonb, -- тело сущности
    "select" text default null -- выбор только заданных полей сущности
) returns jsonb language plpgsql as $body$ declare -- возвращающую json на языке PL/pgSQL
    url text default format($$http(s)://1c.host.name/api/odata/standard.odata/%s(guid'%s')?$$, curl_easy_escape(entity), curl_easy_escape(guid::text)); -- объявляем и конструируем адрес
    text text; -- объявляем вспомогательную переменную
begin
    perform curl_easy_setopt_customrequest('PATCH'); -- задаём тип запроса
    perform curl_easy_setopt_postfields(convert_to(jsonb::text, 'utf-8')); -- задаём тело
    perform curl_easy_setopt_url(url); -- задаём адрес
    perform curl_header_append('Accept', 'application/json'); -- задаём тип ответа
    perform curl_easy_perform(); -- выполняем запрос
    text = convert_from(curl_easy_getinfo_data_in(), 'utf-8'); -- получаем результат
    begin jsonb = text; exception when invalid_text_representation then raise exception '%', text; end; -- пытаемся преобразовать результат в json, а в случае неудачи поднимаем исключение
    if jsonb->'odata.error' is not null then raise exception '%', jsonb->'odata.error'->'message'->>'value'; end if; -- если в результате ошибка, то поднимаем исключение
    if "select" is not null then return read(entity, (jsonb->>'Ref_Key')::uuid, "select"); end if; -- если задан выбор полей, то заново читаем и возвращаем сущность
    return jsonb; -- иначе просто возвращаем сущность
end;$body$;

Можно ещё сделать кеширование при чтении и обновление только при изменении.

Теги:
Хабы:
Рейтинг0
Комментарии4

Публикации

Истории

Работа

Python разработчик
193 вакансии
Аналитик 1С
5 вакансий
Программист 1С
115 вакансий
Data Scientist
104 вакансии
Консультант 1С
159 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
24 сентября
Astra DevConf 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн