0

I am trying to put 2fa in a single page on the registeration View. I was following this advice to put forms inside a single View answer. Code below:

Actually I have two questions:

  1. While i'm checking the validity of my form

rform.is_valid() -> False

my querydict entries after filling the form are:

<QueryDict: {'csrfmiddlewaretoken': ['b7bAYqqW7IFX93d8U8fsvHeWDvW9fn7HRt8cBcpGx9QHRXDfb1thhH5q2r7W3jmC'], 'register-phone_number_0': ['+224'], 'register-phone_number_1': ['123123123'], 'register-password1': ['Fq7dzcBnkksAVVi'], 'register-password2': ['Fq7dzcBnkksAVVi'], 'register': ['']}>

it returns false, even though I had seperate the two forms.

  1. While I submit the first form 'rform' I just want it to send a SMS message so I don't want to refresh the page because it erases the password field which already filled. Is there anyway to do this? the return statment

return self.render_to_response({'rform': rform, 'tform': tform})

returns everything filled except the password.

My expected flow is:

User fills phone and pass -> press the send button (POST the number and authentication request via twillio) -> User gets the SMS message -> User fills in the token -> Press the Save button which saves the user instance

Thank you for the answers

form

class RegisterForm(forms.ModelForm):
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Konfirmasi Password', widget=forms.PasswordInput)

    class Meta:
        model = Account
        fields = ('phone_number', )
        widgets = {
            'phone_number': PhoneNumberPrefixWidget(initial='+62'),
        }
        labels = {
            'phone_number': 'Phone Number',
        }

    def clean_password2(self):
        # Check that two passwords match
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Password don't match")
        validate_password(password2)
        return password2

    def save(self, commit=True):
        #saved provided password in hashed format
        user = super(RegisterForm, self).save(commit=False)
        user.set_password(self.cleaned_data['password1'])
        if commit:
            user.save()
        return user

class TokenForm(forms.Form):
    token = forms.CharField(
        label='Code Konfirmasi', max_length=7, widget=forms.TextInput, required=False)

view

def _get_form(request, formcls, prefix):
    data = request.POST if prefix in request.POST else None
    return formcls(data, prefix=prefix)

class RegisterView(TemplateView):
    template_name = 'authentication/register.html'

    def get(self, request, *args, **kwargs):
        return self.render_to_response({'rform': RegisterForm(prefix='register'), 'tform': TokenForm(prefix='token')})

    def post(self, request, *args, **kwargs):
        rform = _get_form(request, RegisterForm, 'register')
        tform = _get_form(request, TokenForm, 'token')
        print(rform.is_valid())
        if rform.is_bound and rform.is_valid():
            phone = rform.cleaned_data['phone_number']
        elif tform.is_bound and tform.is_valid():
            pass
        return self.render_to_response({'rform': rform, 'tform': tform})

HTML

 <form method='POST'> 
  {% csrf_token %}
  {{ rform.phone_number|as_crispy_field }}
  <div class="row">
    <div class="col-6">
      {{ rform.password1|as_crispy_field }}
    </div>
    <div class="col-6">
      {{ rform.password2|as_crispy_field }}
    </div>
  </div>
  <div class="row align-items-center">
    <div class="col">
      <button type='submit' name="{{rform.prefix}}" class='btn btn-success'>Send Code</button>
    </div>
  </div>
</form>

<form>
  <div class="col-3">
    {{ tform.token|as_crispy_field }}
  </div>
  <button type='submit' name="{{tform.prefix}}" id="submit_register" class='btn btn-success'>Submit</button>
</form>
Dion Dion
  • 3
  • 2

0 Answers0