Search code examples
pythondjangodjango-formspytzdjango-timezone

Django form validation failing - pytz and choices


I am trying to let the user set which timezone they are in, however form validation .is_valid() is failing and cannot figure out why.

  • The timezone value for a user is stored in a Profile model.
  • Using ChoiceField and pytz.common_timezones to fill the form field

This would be appear to be quite simple to do, the only thing thats different to my usual way is that the data filling the combo/select box is the use of a ChoiceField and the data is coming from pytz.

I may switch to django-timezone-field to solve this, but I would like to understand why it is failing. I have included all relevant (I think) code below. Any suggestions?

models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

    timezone = models.CharField(
        max_length=255,
        blank=True,
    )

forms.py

class ProfileEditForm(forms.Form):

    profile_timezone = forms.ChoiceField(choices=[(x, x) for x in pytz.common_timezones])

views.py

@login_required
def userprofile_edit(request):

    if request.method == "POST":
        profile_edit_form = ProfileEditForm()

        if profile_edit_form.is_valid():
            cd = profile_edit_form.cleaned_data

            user = User.objects.get(id=request.user.id)

            user.profile.timezone = cd['timezone']
            user.profile.save()

            messages.success(request, "Profile updated successfully", fail_silently=True)
            return redirect('coremgr:userprofile', request.user.id)

        else:
            messages.error(request, "Error occured. Contact your administrator", fail_silently=True)
            print "error: form not valid"
    else:
        profile_edit_form = ProfileEditForm()

    context = {
        'profile_edit_form': profile_edit_form,
    }

    return render(request, 'apps/coremgr/userprofile_edit.html', context)

template

<form name="formprofile" method="POST" action="">
{% csrf_token %}

<p id="profile_timezone" class="form-inline">
{{ profile_edit_form.profile_timezone.errors }}
Timezone:
{{ profile_edit_form.profile_timezone }}
</p>

<button id="id_btn_profile_edit_save" type="submit" class="btn btn-default" tabindex=7>Save</button>
</form>

Solution

  • add request.POST in form

    if request.method == "POST":
    
         profile_edit_form = ProfileEditForm(request.POST)