«Где моя кнопка? Почему она неактивна?» Как часто программист может слышать эти слова от пользователей своего продукта? Скорее всего, более чем очень часто для того, чтобы задуматься, а может быть продукт сам должен отвечать на этот вопрос пользователей.
Вот приблизительно так выглядит обычная неактивная кнопка, которая, по какой-либо причине, в данный момент не доступна пользователю:
Она безмолвна, не интерактивна и не представляет пользователю ни малейшей информации о том, почему она находится в этом состоянии и при каких условиях станет активной. А вот как могла бы выглядеть «облагороженная», более информативная неактивная кнопка:
В чем же соль, спросите вы? А вот о том, как можно описывать правила на языке программирования Python, чтобы эти правила одновременно вычисляли статус активности кнопки и предоставляли отчет о причине в случае если кнопка должна быть деактивирована, я бы и хотел рассказать в этой статье.
Используя библиотеку собственного изготовления можно описать следующее правило на языке программирования Python:
Классы логических операций принимают операнды, обернутые в
Тогда использовать это правило, например в шаблоне Mako, можно следующим образом:
Как видно из примера, объект
В арсенале библиотеки доступны операции
В результате поиска в сети мне не удалось обнаружить что-либо похожее, поэтому пришлось написать свою библиотеку. Первая версия была выпущена совсем недавно. Мне будет очень интересно узнать о вашем опыте решения этой маленькой, но иногда довольно актуальной, задачи.
Вот приблизительно так выглядит обычная неактивная кнопка, которая, по какой-либо причине, в данный момент не доступна пользователю:
Она безмолвна, не интерактивна и не представляет пользователю ни малейшей информации о том, почему она находится в этом состоянии и при каких условиях станет активной. А вот как могла бы выглядеть «облагороженная», более информативная неактивная кнопка:
В чем же соль, спросите вы? А вот о том, как можно описывать правила на языке программирования Python, чтобы эти правила одновременно вычисляли статус активности кнопки и предоставляли отчет о причине в случае если кнопка должна быть деактивирована, я бы и хотел рассказать в этой статье.
Используя библиотеку собственного изготовления можно описать следующее правило на языке программирования Python:
from rules import _and_, _or_
# The rule
def can_user_add_comment(user, topic):
return _and_(
lambda: (user, “Вы не авторизованы”),
lambda: (user.is_status_active(), “Ваша учетная запись заблокирована”),
lambda: _or_(
lambda: (user.is_in_admin_group(), “Вы не администратор”),
lambda: _and_(
lambda: (topic.is_status_open(), “тема закрыта”),
lambda: (user.has_enough_karma_to_add_comment(), “у Вас не достаточно кармы для комментирования”),
lambda: (user.is_below_comments_per_minute_quota(), “Вы комментируете слишком интенсивно, повторите попытку через пару минут”),
),
),
)
Классы логических операций принимают операнды, обернутые в
lambda
, которые будут вызваны для вычисления значений при необходимости. Т.е. вычисления происходят по «укороченной схеме», например, _and_
вычисляет значения своих аргументов до первого False
, _or_
— до первого True
. Каждый операнд состоит из собственно тестируемого значения (первый элемент кортежа) и сообщения (второй элемент кортежа), которое используется когда тестируемое значение приняло значение False
. Так же, при необходимости, можно опускать сообщения для не значимых частей правила (операндов) с точки зрения информирования пользователя.Тогда использовать это правило, например в шаблоне Mako, можно следующим образом:
<%
user = get_authenticated_user()
granted = can_user_add_comment(user, current_topic)
%>
<input
type=”button”
value=”Добавить комментарий”
title=”${”Добавить комментарий” if granted else unicode(granted)}”
${“disabled” if not granted else “”}
/>
Как видно из примера, объект
granted
, полученный в результате вызова функции can_user_add_comment()
, в булевом контексте сообщает статус активности кнопки, а в строковом контексте сообщает причину, если в булевом контексте он вернул значение False
. Причина неактивности кнопки записывается в ее title
и извлекается пользователем при наведении на нее курсора мыши. По умолчанию в отчет попадают только конкретные сообщения, результат вычисления правил которых оказался False
. Но так же возможно сгенерировать полный древовидный отчет о том, какие логические ветки всего правила вернули значение False
. Для этого надо вызвать granted.build_report()
или granted.build_html_report()
.В арсенале библиотеки доступны операции
_and_
, _or_
, _not_
и _true_
.В результате поиска в сети мне не удалось обнаружить что-либо похожее, поэтому пришлось написать свою библиотеку. Первая версия была выпущена совсем недавно. Мне будет очень интересно узнать о вашем опыте решения этой маленькой, но иногда довольно актуальной, задачи.