Django Forms; Отмените выбор с помощью ModelForm

Я хочу скрыть или показать некоторые варианты выбора в зависимости от страницы. Например,

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__ вы можете управлять этим через self.fields['topic'].choices.

The Pjot 17.12.2018 08:33
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
204
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как сказал Пьот в комментариях, вы можете динамически заполнять значения методом __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

user10766253 17.12.2018 10:05

@dude насколько мне известно, вы можете, как и с любой другой формой, убедиться, что вы делаете это после super().__init__(*args, **kwargs), на самом деле я делал это с ModelForms много в нескольких проектах.

PaK-Zer0 17.12.2018 10:10

Единственная проблема, которую я вижу, заключается в том, что вы используете CharField как в моделях, так и в методе формы __init__. Думаю, мы все это время говорили о ChoiceField, верно? Может быть, это причина AttributeError?

PaK-Zer0 17.12.2018 10:46

Ошибок больше нет, но поле не отображается. Также, когда я использую ChoiceField, возникает ошибка. Я думаю, что это дается объектом Form, а не ModelForm.

user10766253 17.12.2018 10:52

Давайте попробуем еще кое-что: добавьте эти два в начало вашего forms.py сразу после последнего импорта: from pprint import pprint logger = logging.getLogger(__name__) И затем это после super в init logger.warn(pprint(vars(self))) И затем проверьте поля, отображаемые в консоли сервера разработки django

PaK-Zer0 17.12.2018 10:59

Я нашел простой способ сделать это. Можно переопределить вот так.

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')
   ]

Другие вопросы по теме