django: исключить определенные элементы формы на основе условия

У меня есть некоторые поля формы, которые я хочу включить / исключить, исходя из того, выполняется ли определенное условие. Я знаю, как включать и исключать элементы формы, но мне трудно это делать, когда я хочу, чтобы эти элементы отображались на основе результата функции.

Вот моя форма:

class ProfileForm(ModelForm): # this_team = get Team instance from team.id passed in # how? def draft_unlocked(self): teams = Team.objects.order_by('total_points') count = 0 for team in teams: if team.pk == this_team.pk: break count += 1 now = datetime.datetime.now().weekday() if now >= count: # show driver_one, driver_two, driver_three else: # do not show driver_one, driver_two, driver_three class Meta: model = Team 

То, что я пытаюсь выполнить, основывается на позиции общих очков, команда не должна менять свой драйвер до указанного дня. Как и в, последняя команда в турнирной таблице может добавить / сбросить драйвер в понедельник, вторая – последняя команда может добавить / сбросить во вторник и так далее …

Итак, первая проблема – как я могу получить экземпляр Team внутри самой формы из идентификатора, который был передан. И как мне включить / исключить на основе результата draft_unlocked ().

Или, может быть, есть лучший способ сделать все это?

Большое спасибо всем.

2 Solutions collect form web for “django: исключить определенные элементы формы на основе условия”

На самом деле это довольно просто (условные настройки поля) – вот краткий пример:

 from django.forms import Modelform from django.forms.widgets import HiddenInput class SomeForm(ModelForm): def __init__(self, *args, **kwargs): # call constructor to set up the fields. If you don't do this # first you can't modify fields. super(SomeForm, self).__init__(*args, **kwargs) try: # make somefunc return something True # if you can change the driver. # might make sense in a model? canchangedriver = self.instance.somefunc() except AttributeError: # unbound form, what do you want to do here? canchangedriver = True # for example? # if the driver can't be changed, use a input=hidden # input field. if not canchangedriver: self.fields["Drivers"].widget = HiddenInput() class Meta: model = SomeModel 

Итак, ключевые моменты из этого:

  • self.instance представляет собой связанный объект, если форма привязана. Я считаю, что он передается как именованный аргумент, поэтому в kwargs , который родительский конструктор использует для создания self.instance .
  • Вы можете изменить свойства поля после вызова родительского конструктора.
  • виджеты – это способы отображения форм. HiddenInput в основном означает <input type="hidden" .../> .

Существует одно ограничение; Я могу вмешиваться в ввод, чтобы изменить значение, если я изменяю данные POST / GET. Если вы не хотите, чтобы это произошло, что-то, что нужно учитывать, переопределяет метод проверки формы (clean ()). Помните, что все в Django – это просто объекты, а это означает, что вы можете фактически модифицировать объекты класса и добавлять данные к ним наугад (это не будет сохраняться). Итак, в своем __init__ вы могли:

 self.instance.olddrivers = instance.drivers.all() 

Затем в вашем чистом методе для указанной формы:

 def clean(self): # validate parent. Do this first because this method # will transform field values into model field values. # ie instance will reflect the form changes. super(SomeForm, self).clean() # can we modify drivers? canchangedriver = self.instance.somefunc() # either we can change the driver, or if not, we require # that the two lists are, when sorted, equal (to allow for # potential non equal ordering of identical elements). # Wrapped code here for niceness if (canchangedriver or (sorted(self.instance.drivers.all()) == sorted(self.instance.olddrivers))): return True else: raise ValidationError() # customise this to your liking. 

Вы можете сделать то, что вам нужно, добавив свой собственный init, где вы можете передать идентификатор, когда вы создаете экземпляр класса формы:

 class ProfileForm(ModelForm): def __init__(self, team_id, *args, **kwargs): super(ProfileForm, self).__init__(*args, **kwargs) this_team = Team.objects.get(pk=team_id) teams = Team.objects.order_by('total_points') count = 0 for team in teams: if team.pk == this_team.pk: break count += 1 now = datetime.datetime.now().weekday() if now >= count: # show driver_one, driver_two, driver_three else: # do not show driver_one, driver_two, driver_three class Meta: model = Team #views.py def my_view(request, team_id): profile_form = ProfileForm(team_id, request.POST or None) #more code here 

Надеюсь, что это поможет тебе.

  • Реализация сигнала Django post_save ()
  • Django 1.7 - App 'your_app_name' не имеет миграций
  • В администраторе Django, как я могу скрыть кнопки «Сохранить и продолжить» и «Сохранить и добавить еще» в администраторе модели?
  • Django Rest Framework добавляет метод уровня класса к api
  • Получить проверку params на viewets.ModelViewSet
  • Развертывание Google Analytics с помощью Django
  • Деградация производительности для Django с Gunicorn, развернутая в Heroku
  • django-admin: добавьте дополнительную строку с итогами
  • Обработка статических файлов, которые не относятся к приложению в Django
  • Проверка Django, если флажок установлен
  • django-orm: как обновить значение поля отношения один к одному
  • Python - лучший язык программирования в мире.