Чистый способ настройки форм на основе группы пользователей в Django
Я хочу настроить формы моей модели на основе группы пользователей. Настройки, о которых я говорю, небольшие, но чтобы дать вам представление, мои "настройки" будут примерно такими :
- пользователи в GroupA будут иметь BooleanField с True по умолчанию, даже если по умолчанию False для других .
- пользователи в GroupB будут иметь CharField (вводимый текст) скрытым (не изменяемым)
- пользователи в группеС будут иметь не те же опции, что и другие для CharField с опциями (различные опции в select) .
- ...
В настоящее время я фактически добился этого, выполняя смесь логики в моем views.py
и в моем forms.py
.
Но мне не очень нравится смешивать логику в 2 разных файлах, поэтому я пришел спросить ваше мнение о том, какой способ является лучшим (наиболее чистым) на ваш взгляд и как его достичь.
Вот 2 техники, о которых я думаю:
1. Создание формы для каждой группы в forms.py
.
Это был бы самый чистый способ.
Создавая форму для каждой группы (MyModelGroupAForm(ModelForm), MyModelGroupBForm(ModelForm), ...) я могу легко изменить поле/вход/... в моем forms.py
файле каждый раз, когда запрашивается изменение и/или создается группа.
Затем, все, что мне нужно сделать, это переопределить метод get_form(self)
в моих MyModelCreateView
и MyModelUpdateView
, и изменить self.form_class
на правильную форму, основанную на группе пользователя, как показано ниже:
Class MyModelCreateView(CreateView):
model = MyModel
form_class = MyModelDefaultForm
def get_form(self):
if self.request.user.groups.filter(name='GroupA').exists():
self.form_class = MyModelGroupAForm
elif self.request.user.groups.filter(name='GroupB').exists():
self.form_class = MyModelGroupBForm
elif ... # another group
form = super().get_form()
return form
...
Недостатком этой техники является то, что мне придется сделать много форм с одинаковыми данными: например, одно из моих полей запрашивает виджет. Это означает, что КАЖДАЯ форма, которую я создаю для КАЖДОЙ группы, должна будет указывать my_field = forms.CharField(widget=DatePickerInput())
, так как указать виджет в определении модели в models.py
невозможно. Это кажется не совсем DRY... (есть ли какое-то наследование между формами? Если бы я мог заставить форму наследоваться от абстрактной формы, мне бы не пришлось каждый раз определять поле)
2. Обработка всей логики в файле views.py.
Это делает мой views.py
файл очень длинным...
В принципе, в классе MyModelCreateView
в моем views.py
я бы изменил поле в методе get_form()
на основе группы self.request.user
. И там я бы реализовал много логики типа if/else/switch, основанной на группе и изменении каждого поля, как показано ниже:
Class MyModelCreateView(CreateView):
model = MyModel
form_class = MyModelDefaultForm
def get_form(self):
form = super().get_form()
if self.request.user.groups.filter(name='GroupA').exists():
# change the default of a boolean field to True, instead of False
# another change specific to group A making the method even longer
# ...
elif self.request.user.groups.filter(name='GroupB').exists():
# hide/remove a CharField
# another change specific to group B making the method even longer
# ...
elif ... # another group
return form
Имо, это не очень чисто. Пока у меня меньше 10 групп, так что все в порядке. Но позже у меня будет гораздо больше групп, что означает, что моя логика if/elif/elif/... будет огромной...
Кроме того, мне нужно будет скопировать эту логику в MyModelUpdateView
также в
...
Не совсем DRY...
Что вы думаете? Какой самый лучший/чистый способ сделать это?
(На данный момент я делаю смесь из technic 1 и technic 2)