Как добавить поле формы Django динамически в зависимости от того, было ли заполнено предыдущее поле?

У меня есть форма (Formset) для обновления пользователями своих профилей. Это стандартная форма модели User, и пользовательская форма модели Participants. Теперь, в случаях, когда участник предоставляет свой номер телефона, мне нужно обновить всю форму с новым "Кодом", введенным динамически. И участник будет вводить код, который он получил в SMS. Вот как я пытаюсь это сделать:

def post(self, request, *args, **kwargs):
    self.object = self.get_object()
    form = self.get_form()

    if form.is_valid():
        form.save()
        seller_form = SellerForm(self.request.POST, instance=self.object.seller)
        if seller_form.is_valid():
            seller = self.request.user.seller
            seller.inn = seller_form.cleaned_data.get('inn')
            if seller_form.cleaned_data.get('phone_number'):
                seller_form.fields['code'] = models.CharField(max_length=4)
                return render(request, self.template_name, {'form': form, 'seller_form': seller_form})
            seller.save()
            return HttpResponse('Seller updated')
    return render(request, self.template_name, {'form': form, 'seller_form': seller_form})

Я не уверен, что это тот способ, которым я могу добавить дополнительное поле. Что бы вы предложили для решения этой ситуации?

Используемая мной техника заключается в том, что первоначально поле на форме скрыто. Когда форма становится действительной, я заставляю его стать видимым, а затем снова отправляю форму. В представлениях на основе классов и контура:

class SomeThingForm( forms.Modelform):
    class Meta:
        model=Thing
        fields = [ ...

    confirm = forms.BooleanField( 
        initial=False, required=False, widget=forms.widgets.HiddenInput,
        label='Confirm your inputs?' )

class SomeView( CreateView): # or UpdateView
    form_class = SomeThingForm
    template_name = 'whatever'

    def form_valid( self, form):

        _warnings = []
        # have a look at cleaned_data
        # generate _warnings (a list of 2-tuples) about things which
        # aren't automatically bad data but merit another look

        if not form.cleaned_data['confirm'] and _warnings:
            form.add_error('confirm', 'Correct possible typos and override if sure')
            for field,error_text in _warnings:
                form.add_error( field, error_text) # 'foo', 'Check me'
                # make the confirm field visible
                form.fields['confirm'].widget = forms.widgets.Select(
                    choices=((0, 'No'), (1, 'Yes')) )
            # treat the form as invalid (which it now is!)
            return self.form_invalid( form)

    # OK it's come back with confirm=True
    form.save()  # save the model
    return redirect( ...)

Для этого вопроса, я думаю, вы замените confirm на sms_challenge, Charfield или IntegerField, изначально скрытый, со значением по умолчанию, которое никогда не будет правильным ответом. Когда остальная часть формы пройдет проверку, будет вызвано form_valid(), а затем тот же поток программы, за исключением того, что вы также отправляете SMS на номер телефона в clean_data.

        _warnings = [] 
        # retrieve sms_challenge that was sent
        if form.cleaned_data['sms_challenge'] != sms_challenge:
            _warnings.append( ['sms_challenge', 'Sorry, that's not right'] )
        if _warnings:
            ...
            form.fields['sms_challenge'].widget = forms.widgets.TextInput
            return self.form_invalid( form)

Думаю, это должно сработать.

Вернуться на верх