Я использую django-fsm на поле state
(тип FSMField) для отслеживания пробных проб через процесс. Мне нужно, чтобы некоторые опытные пользователи могли «перескакивать» объекты из одного состояния в другое, регистрировать и отправлять уведомления, когда это происходит. Мой вопрос: Как написать этот переход, избегая повторения кода (т. Е. СУХОЙ)?Можете ли вы закодировать переход django-fsm, который нацелен на произвольное состояние?
Подробнее:
Я установил protected=True
на моем FSMField: мне очень нравится защиты он предоставляет - никаких других путей кода не в состоянии изменить state
.
Вот основы (примечание: не полный код, не будут работать, только для иллюстрации)
class SampleTube(model.Model):
state = FSMField(default='new', choices=(...), protected=True)
@transition(field=state, source='*', target='*', permission='my_app.superpowers') # <-- problem 1
def set_state(self, user, new_state):
assert is_valid_state(new_state)
log_event(self, user, new_state)
send_notification(self, self.owner)
self.state = new_state # <-- problem 2
Проблема 1: Как я понимаю, я могу использовать только одно значение строки для target
(docs link). Справедливо. Мне нравится то, что модели метода вызова автоматически устанавливают state
. Поэтому я не думаю, что могу написать переход к произвольному состоянию.
Проблема 2: Если я хочу, чтобы сохранить protected=True
(по указанным выше причинам), я не могу напрямую изменять state
поля (поднимает AttributeError
, как описано)
ли я прибегнуть к написанию этого в моем модель класса? Есть ли какой-то метод метапрограммирования, который будет держать меня сухим?
@transition(field=state, source='*', target='used', permission='myapp.superpowers')
def set_used(self, user):
# ...
@transition(field=state, source='*', target='received', permission='myapp.superpowers')
def set_received(self, user):
# ...
#... loads more set_xyz methods that all have the same signature...
Поэтому я хочу, чтобы решить эту проблему (кроме с удовлетворением краткого кода) является то, что число возможных состояний достаточно велико (10+).
[править] Происходит мне, что временно, явно отключить защиту на state
поле внутри метода set_state
может быть еще один способ приблизиться к этому, если бы я мог работать, как ...
Вообще говоря, я не вижу правильный ответ на ваш вопрос, б/с вопрос неверен. Pythonic подход настаивает на том, что явный лучше, чем неявный. Это то, что делает django-fsm. Как только ваше требование изменится, и вам нужно пропустить или выполнить отдельное действие при изменении состояния суперпользователя, любой общий подход приведет вас к огромному рефакторингу. – kmmbvnr
Я надеялся найти способ, который является pythonic и не повторяющимся. Я думаю, что я являюсь явным, потому что в сигнатуре метода, предложенной явным образом, есть параметр 'new_state' в качестве параметра и явно имеет разрешение, требуемое в декораторе. Возможно, я скучаю по тебе. – mozz100
Я думаю, вы неправильно поняли СУХОЙ. DRY означает, что один вопрос дает ответ только в одном месте. В этом случае вы пытаетесь решить N вопросов в одном месте (когда и как администратор может изменить состояние XXX в YYY). Правильное решение DRY должно состоять в том, чтобы иметь N переходных методов состояния, который вызывает один метод log/send_notify. – kmmbvnr