Antef Tech
Antef Tech

Reputation: 11

Prevent form refresh on validation error django

I have a RegisterForm that inherits from ModelForm with RegisterView that inherits from FormView. If every field data is valid, the user gets successfully created and is redirected to login page. But if there is a validation error, it shows the field error below that field and the form gets refreshed and all the fields data is lost. How to avoid form refreshing so that user need not to fill the details again and again.

forms.py

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

    class Meta:
        model = UserModel
        fields = (
            'first_name',
            'last_name',
            'username',
            'password1',
            'password2',
            'current_email',
        )

    def __init__(self, social_email=None, social_fname=None, social_lname=None, 
        social_uname=None,*args, **kwargs):
        super(RegisterForm, self).__init__(*args, **kwargs)
        self.current_email = None
        self.social_email = social_email
        self.social_fname = social_fname
        self.social_lname = social_lname
        self.social_uname = social_uname

    def clean(self, *args, **kwargs):
        username = self.cleaned_data.get('username')
        self.current_email = self.cleaned_data.get('current_email')
        if self.social_email:
            self.current_email = self.social_email

        if not username:
            raise forms.ValidationError({"username":"Username can't be empty"})
        if not self.current_email:
            raise forms.ValidationError({"current_email":"Email can't be empty"})
        qs = UserModel.objects.filter(username=username)
        qs_email = UserModel.objects.filter(current_email=self.current_email)
        if qs.exists():
            raise forms.ValidationError({"username":"Username is already taken"})
        if qs_email.exists():
            raise forms.ValidationError({"current_email":"Email has already been registered"})
        return self.cleaned_data

    def save(self, commit=True):
        user = super().save(commit=False)
        current_email = self.cleaned_data.get('current_email')
        password = self.cleaned_data.get('password1')
        user.set_password(password)
        if self.social_email:
            user.is_active = True
        user.save()
        return user

views.py

class RegisterView(ContextMixin, FormView):
    form_class = RegisterForm
    template_name = 'accounts/register.html'
    title = 'Register'

    @method_decorator(sensitive_post_parameters('password'))
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, *args, **kwargs):
        self.kwargs['social_email'] = SOCIAL_USER_EMAIL
        self.kwargs['social_fname'] = SOCIAL_USER_FNAME
        self.kwargs['social_lname'] = SOCIAL_USER_LNAME
        if SOCIAL_USER_EMAIL:
            self.kwargs['social_uname'] = SOCIAL_USER_EMAIL.split('@',1)[0]
        return super(RegisterView, self).dispatch(*args, **kwargs)

    # Passes view kwargs to html
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if SOCIAL_USER_EMAIL:
            context['social_email'] = self.kwargs['social_email']
            context['social_fname'] = self.kwargs['social_fname']
            context['social_lname'] = self.kwargs['social_lname']
            context['social_uname'] = self.kwargs['social_uname']
            # context['social_image'] = SOCIAL_USER_IMAGE
        return context

    # Passes view kwargs to form
    def get_form_kwargs(self):
        kwargs = super(RegisterView, self).get_form_kwargs()
        kwargs.update(self.kwargs)
        return kwargs

    def form_valid(self, form):
        form.save()
        if not self.kwargs['social_email']:
            return render(self.request, 'accounts/success.html', {
            'title':"You've registered successfully",
            'body':"You've successfully registered at antef! Please verify the link sent at " + 
            form.current_email
            })            

        return render(self.request, 'accounts/success.html', {
            'title':"You've registered successfully",
            'body':"You've successfully registered with your " + self.kwargs['social_email'] + " account."})

Upvotes: 1

Views: 1846

Answers (1)

Bidhan Majhi
Bidhan Majhi

Reputation: 1370

First, you don't need validation error for empty inputs, just add required = True in your forms.py or in your model.

Second you are not returning anything after validation error, which making your form empty after refresh.

You can also check email and username separately, for better use,

def clean_email(self):
     email = self.cleaned_data.get('email')
     if your_condition:
        raise forms.ValidationError()
     return email

def clean_username(self):
     username = self.cleaned_data.get('username')
     if your_condition
         raise forms.ValidationError
     return username

Upvotes: 2

Related Questions