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

от автора

Для приготовления 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$;

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


ссылка на оригинал статьи https://habr.com/ru/post/666346/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *