Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6909239
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T08:39:52+00:00 2026-05-27T08:39:52+00:00

I keep getting the feeling that I’m benefitting from maybe half of the features

  • 0

I keep getting the feeling that I’m benefitting from maybe half of the features of Django forms, but suffering greatly at the other half of the “features.”

Here’s an interesting use case. I have a form that allows a user to edit their “profile.” This contains a few objects, namely the following:

class UserProfile(models.Model):
    default_address = models.ForeignKey("Address")
    default_phone_number = models.ForeignKey("PhoneNumber")

class Address(models.Model):
    name = models.CharField()
    street_address = models.CharField()
    street_address_2 = models.CharField()
    city = models.CharField()
    country = models.ForeignKey("locality.Country")
    territory = models.ForeignKey("locality.Territory", blank=True, null=True)
    postal_code = models.CharField()

class PhoneNumber(models.Model):
    name = models.CharField()
    number = models.CharField()

The “locality.*” models are from another project I wrote called django-locality, and are viewable here.

(I wrote django-locality as there simply wasn’t a way of doing what I wanted at the time. I was looking to simply create this form, which included a country and a territory. As there wasn’t anything that gave me database access to countries and their territories, I built something to do the job. I needed to allow users to select a country and only be able to select a territory for that country if the country had territories. Pretty simple, but it evidently hadn’t been done before.)

So here’s where things get a bit more complicated. My form edits django.contrib.auth.models.User‘s first_name and last_name fields, as well as creates or updates Address and PhoneNumber instances owned by the UserProfile class.

Validation gets really complicated really quickly. I need to make sure that 1. if a country has territories, a territory must be selected, and 2. if a territory is selected, it must belong to the selected country. Also, I ended up essentially providing a blank select control in my template, as territories have to be dynamically fetched based on the selected country. It would have been nice to simply have a form field like a “ModelOptgroupChoiceField” which would have allowed me to group my territories by their country’s abbreviation, in a select control with optgroups for each country then filter these out in JavaScript, but whatever. I was able to at least get it working after much deliberation and experimentation.

Another complication in validation comes with validation of phone numbers and postal-codes: how am I supposed to validate them? Sure, django.contrib.localflavors provides controls, but provides basically no single auto-localizing control to drop in. I could write some crazy logic which would use an input country’s abbreviation to look things up in the django.contrib.localflavors package and dynamically set my phone_number and postal_code fields in my form to the right values, but seriously? Do I need to go to a hack at that extreme of a length to get things working? I basically just gave up entirely on validation/formatting for these fields.

class ProfileEditForm(forms.Form):

    default_error_messages = {
        'invalid_territory': _("Please select a territory."),
        'invalid_country': _("Please select a country."),
    }

    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    street_address = forms.CharField(max_length=128)
    street_address_2 = forms.CharField(max_length=128, required=False)
    city = forms.CharField(max_length=128)
    country = forms.ModelChoiceField(Country.objects.all().order_by('name'), 
            empty_label=u'', to_field_name='iso2')
    territory = forms.ModelChoiceField(Territory.objects.all().order_by(
            'country__name', 'name'), empty_label=u'', to_field_name='pk')
    zipcode = forms.CharField(max_length=12)
    phone_number = forms.CharField(max_length=16)

    def __init__(self, *args, **kwargs):
        if 'user' in kwargs:
            user = kwargs['user']
            del kwargs['user']
            kwargs['initial'] = {
                'first_name': user.first_name,
                'last_name': user.last_name,
                'street_address': user.profile.default_address.street_address
                    if user.profile.default_address != None else '',
                'street_address_2': user.profile.default_address.street_address_2 
                    if user.profile.default_address != None else '',
                'city': user.profile.default_address.city
                    if user.profile.default_address != None else '',
                'country': user.profile.default_address.country.iso2
                    if user.profile.default_address != None else None,
                'territory': user.profile.default_address.territory.pk
                    if user.profile.default_address != None else None,
                'zipcode': user.profile.default_address.postal_code
                    if user.profile.default_address != None else '',
                'phone_number': user.profile.default_phone_number.number
                    if user.profile.default_phone_number != None else None,

            }

        super(ProfileEditForm, self).__init__(*args, **kwargs)

    def clean(self):
        territory = self.cleaned_data.get('territory', None)
        country = self.cleaned_data.get('country', None)

        if territory == None or Territory.objects.filter(country__id = country.pk, 
                pk=territory.pk).count() == 0:
            self._errors['territory'] = self.error_class([
                self.default_error_messages['invalid_territory']])
            if territory != None:
                del self.cleaned_data.territory
        else:
            self.cleaned_data['territory'] = Territory.objects.get(
                country__id = country.pk, abbr = territory.abbr)

        # format phone-number
        if re.match(r'^\d{10}$', self.cleaned_data['phone_number']):
            match = re.match(r'^(\d{3})(\d{3})(\d{4})$', self.cleaned_data[
                'phone_number'])
            self.cleaned_data['phone_number'] = "%s-%s-%s" % (match.group(1),
                    match.group(2), match.group(3))

        return self.cleaned_data

If you think my form is a bit complicated, wait until you see my template in order to output things properly:

    <form method="post" action="">
        <fieldset>
            {% csrf_token %}
            <legend>Your Name</legend>
            <div class="clearfix{% if form.first_name.errors %} error{% endif %}">
                <label for="first_name_input">First Name</label>
                <div class="input">
                    <input id="first_name_input" name="first_name" class="span5" type="text"{% if form.first_name.value %} value="{{form.first_name.value}}"{% endif %}></input>
                    {{ form.first_name.errors }}
                </div>
            </div>
            <div class="clearfix{% if form.last_name.errors %} error{% endif %}">
                <label for="last_name_input">Last Name</label>
                <div class="input">
                    <input id="last_name_input" name="last_name" class="span5" type="text"{% if form.last_name.value %} value="{{form.last_name.value}}"{% endif %}></input>
                    {{ form.last_name.errors }}
                </div>
            </div>
        </fieldset>
        <div class="row">
            <div class="span7">
                <fieldset>
                    <legend>Your Address</legend>
                    <div class="clearfix{% if form.street_address.errors %} error{% endif %}">
                        <label for="street_address_input">Address Line 1</label>
                        <div class="input">
                            <input id="street_address_input" name="street_address" class="span5" type="text"{% if form.street_address.value %} value="{{form.street_address.value}}"{% endif %}></input>
                            {{ form.street_address.errors }}
                        </div>
                    </div>
                    <div class="clearfix{% if form.street_address_2.errors %} error{% endif %}">
                        <label for="street_address_2_input">Address Line 2</label>
                        <div class="input">
                            <input id="street_address_2_input" name="street_address_2" class="span5" type="text"{% if form.street_address_2.value %} value="{{form.street_address_2.value}}"{% endif %}></input>
                            {{ form.street_address_2.errors }}
                        </div>
                    </div>
                    <div class="clearfix{% if form.city.errors %} error{% endif %}">
                        <label for="city_input">City</label>
                        <div class="input">
                            <input id="city_input" name="city" data-placeholder="Your City" class="span5"{% if form.city.value %} value="{{form.city.value}}"{% endif %}></input>
                            {{ form.country.errors }}
                        </div>
                    </div>
                    <div class="clearfix{% if form.country.errors %} error{% endif %}">
                        <label for="country_input">Country</label>
                        <div class="input">
                            <select id="country_input" name="country" data-placeholder="Choose a Country..."
                                    class="chzn-select span5"{% if form.country.value %} data-initialvalue="{{form.country.value}}"{% endif %}>
                                <option value=""></option>
                                {% for country in countries %}
                                <option value="{{country.abbr}}"{% if form.country.value == country.iso2 %} selected{% endif %}>{{country.name}}</option>
                                {% endfor %}
                            </select>
                            {{ form.country.errors }}
                        </div>
                    </div>
                    <div class="clearfix{% if form.territory.errors %} error{% endif %}">
                        <label for="territory_input">Territory</label>
                        <div class="input">
                            <select id="territory_input" name="territory" data-placeholder="Choose a State..."
                                class="chzn-select span5" {% if form.territory.value %} data-initialvalue="{{form.territory.value}}"{% endif %}>
                                <option value=""></option>
                            </select>
                            {{ form.territory.errors }}
                        </div>
                    </div>
                    <div class="clearfix{% if form.zipcode.errors %} error{% endif %}">
                        <label for="zipcode_input">Postal Code</label>
                        <div class="input">
                            <input id="zipcode_input" name="zipcode" class="span5" text="text"{% if form.zipcode.value %} value="{{form.zipcode.value}}"{% endif %}></input>
                            {{ form.zipcode.errors }}
                        </div>
                    </div>
                </fieldset>
            </div>
        </div>
        <fieldset>
            <legend>Your Phone Number</legend>
            <div class="clearfix{% if form.phone_number.errors %} error{% endif %}">
                <label for="phone_input" text="text">Phone Number</label>
                <div class="input">
                    <input id="phone_input" name="phone_number" class="span5" text="text"{% if form.phone_number.value %} value="{{form.phone_number.value}}"{% endif %}></input>
                    {{ form.phone_number.errors }}
                </div>
            </div>
        </fieldset>
        <div class="actions clearfix">
            <input type="submit" class="btn primary" style="float:right" value="Save Changes"></input>
        </div>
    </form>

As if that’s not enough, my view is likewise bloated and complicated:

@login_required
def profile_edit(request):
    if request.method == "POST":
        form = forms.ProfileEditForm(request.POST)

        if form.is_valid() == True:
            user = request.user
            profile = user.profile

            user.first_name = form.cleaned_data['first_name']
            user.last_name = form.cleaned_data['last_name']
            user.save()

            address = profile.default_address or models.Address()
            address.name = "Default" if address.name == None else address.name
            address.street_address = form.cleaned_data['street_address']
            address.street_address_2 = form.cleaned_data['street_address_2']
            address.city = form.cleaned_data['city']
            address.country = form.cleaned_data['country']
            address.territory = form.cleaned_data['territory']
            address.postal_code = form.cleaned_data['zipcode']
            address.user_profile = profile
            address.save()

            phone_number = profile.default_phone_number or models.PhoneNumber()
            phone_number.name = "Default" if phone_number.name == None else phone_number.name
            phone_number.number = form.cleaned_data['phone_number']
            phone_number.user_profile = profile
            phone_number.save()

            profile.default_address = address
            profile.default_phone_number = phone_number
            profile.save()

            return redirect("/me/profile/")
    else:
        form = forms.ProfileEditForm(user=request.user)

    return dto(request, "desktop/profile/edit.html", {"form": form,
            "countries": Country.objects.all().order_by('name'),
            "territories": Territory.objects.all().order_by('country__iso2')})

All-in-all, it’s taken well over 12 hours to write this form, excluding the amount of time I’ve spent working on django-locality.

This seems just wrong to me. I was convinced when I was introduced to Django that it would speed up my development tenfold. Somehow, I’m a little less than impressed. Surely, I must be doing something terribly wrong here. Am I doing Django forms wrong?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T08:39:53+00:00Added an answer on May 27, 2026 at 8:39 am

    I think this would make for an excellent wiki discussion.

    Validation gets really complicated really quickly. I need to make sure
    that 1. if a country has territories, a territory must be selected,
    and 2. if a territory is selected, it must belong to the selected
    country. Also, I ended up essentially providing a blank select control
    in my template, as territories have to be dynamically fetched based on
    the selected country. It would have been nice to simply have a form
    field like a “ModelOptgroupChoiceField” which would have allowed me to
    group my territories by their country’s abbreviation, in a select
    control with optgroups for each country then filter these out in
    JavaScript, but whatever. I was able to at least get it working after
    much deliberation and experimentation.

    When I ran into this problem, I used client side validation with javascript to solve the “if this selected, then make sure that is selected” problem.

    As for grouping, I usually employ the multiselect widget from jquery.

    Another complication in validation comes with validation of phone
    numbers and postal-codes: how am I supposed to validate them? Sure,
    django.contrib.localflavors provides controls, but provides basically
    no single auto-localizing control to drop in. I could write some crazy
    logic which would use an input country’s abbreviation to look things
    up in the django.contrib.localflavors package and dynamically set my
    phone_number and postal_code fields in my form to the right values,
    but seriously? Do I need to go to a hack at that extreme of a length
    to get things working? I basically just gave up entirely on
    validation/formatting for these fields.

    For pre-filling/masking fields, use javascript; and for lookups, use ajax calls. It is a lot easier that way.

    As for back end validation; I find that custom fields and validators go a long way.

    django-uni-form is an elegant approach to form rendering that will clean up your templates somewhat.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I keep getting this error when i try to access forms that calls WCF
I keep getting an error saying that @android:style/Widget.Holo.Light.Button.Borderless is not public and so can't
I keep getting this error on emulator: I copied this from a tutorial and
I keep getting a Run Time error that says I am having an Exception
I keep getting an AccessViolationException when calling the following from an external DLL: FILES_GetMemoryMapping(MapFile,
There are a lot of complex forms in my project and I keep getting
Keep getting an error when I run the following. Any help greatly appreciated. John
I keep getting this error saying that it cannot find my javascript function checkpw().
I keep getting that error when trying to access any of my views. I'm
I keep getting an AccessViolationException when calling the following from an external C DLL:

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.