Я хочу скрыть или показать некоторые варианты выбора в зависимости от страницы. Например,
models.py
USA = 'usa'
FRANCE = 'france'
CHINA = 'china'
GERMANY = 'germany'
SPAIN = 'spain'
TOPICS = (
(USA, 'USA'),
(FRANCE, 'France'),
(CHINA, 'China'),
(GERMANY, 'Germany'),
(SPAIN, 'Spain'),
)
topic = models.CharField(
choices=TOPICS,
default=USA,
)
Для страницы я хочу заставить пользователей не выбирать США, поэтому я хочу скрыть США в форме, а также изменить значение по умолчанию. Как я могу это сделать?
Вот мой текущий код. класс AForm (forms.ModelForm):
class Meta:
model = A
fields = ['topic',]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['topic'].choices = ['France', 'Germany', 'Spain']
Произошла ошибка.
ValueError: too many values to unpack (expected 2)
и я заменил его случайными двумя символами, такими как ab
. Один из символов появляется в форме как выбор, хотя я не определял его в модели. Я до сих пор не понимаю, как я могу связать приоритетный выбор с моделью. Как правильно с ModelForm
?
Как сказал Пьот в комментариях, вы можете динамически заполнять значения методом __init__
формы
# put this two on the top of your forms.py, remove them later if you wish
from pprint import pprint
logger = logging.getLogger(__name__)
class YourForm(Form):
# you may set an empty choices list here, we'll override it later
a_choicefield = ChoiceField(label = "My choice field", choices=[('', '---------')])
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# add this log output to inspect the inner guts of your Form/ModelForm
logger.warn(pprint(vars(self)))
# here you may get params from args or kwargs comming from elsewhere
# so you may fill the choices list accordingly
my_dynamic_choices = []
if kwargs['foo']:
my_dynamic_choices = [A, B, C]
else:
my_dynamic_choices = [C, D, E]
self.fields['a_choicefield'] = ChoiceField(label = "My choice field", choices=my_dynamic_choices)
Как я могу это сделать с ModelForm
? Я пробовал этот способ, но есть AttributeError, например, у ModelForm
нет fields
@dude насколько мне известно, вы можете, как и с любой другой формой, убедиться, что вы делаете это после super().__init__(*args, **kwargs)
, на самом деле я делал это с ModelForms много в нескольких проектах.
Единственная проблема, которую я вижу, заключается в том, что вы используете CharField как в моделях, так и в методе формы __init__
. Думаю, мы все это время говорили о ChoiceField, верно? Может быть, это причина AttributeError?
Ошибок больше нет, но поле не отображается. Также, когда я использую ChoiceField, возникает ошибка. Я думаю, что это дается объектом Form
, а не ModelForm
.
Давайте попробуем еще кое-что: добавьте эти два в начало вашего forms.py сразу после последнего импорта: from pprint import pprint logger = logging.getLogger(__name__)
И затем это после super
в init logger.warn(pprint(vars(self)))
И затем проверьте поля, отображаемые в консоли сервера разработки django
Я нашел простой способ сделать это. Можно переопределить вот так.
self.fields['field_name'].choices = list(self.fields['field_name'].choices)[:3]
Это не имеет ничего общего с ModelForm, но с тем, как определяется выбор - ожидается, что варианты будут списком кортежей (value, label)
(посмотрите, как вы определили варианты в своей модели), а не списком значений. Вы хотите:
self.fields['topic'].choices = [
('france','France'),
('germany', 'Germany'),
('spain', 'Spain')
]
или лучше):
self.fields['topic'].choices = [
choice for choice in YourModel.TOPICS
if choice[0] in ('france', 'germany', 'spain')
]
В
__init__
вы можете управлять этим черезself.fields['topic'].choices
.