user2575502
user2575502

Reputation: 703

Django Error "XXXForm" object has no attribute "XXX"

I use Django to build a web app and when I submit a form, I got error:

AttributeError at /CustomerInfo/
'CustomerForm' object has no attribute 'first_name'

The project name is zqxt_views and app name is calc. I create a file named forms.py in the calc folder, see below:
calc/forms.py:

from django import forms

class CustomerForm(forms.Form):
      customer_id = forms.IntegerField(label="Customer ID")
      first_name = forms.CharField(label="First Name", max_length=30)
      last_name = forms.CharField(label="Last Name", max_length=30)

calc/views.py:

# -*- coding: utf-8 -*-
#from __future__ import unicode_literals

#from django.shortcuts import render

from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
import MySQLdb
from calc.models import Customer
from calc.forms import CustomerForm
from django.db import connection

...

def show_save_customer(request):
    # if this is a POST request we need to process the form database
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = CustomerForm(request.POST)
        cursor = connection.cursor()
        query = """ insert into customers (first_name, last_name) values (%s, %s) """
        cursor.execute(query, [form.first_name, form.last_name])
        # check whether it's valid:
        if form.is_valid():
            #process the data
            return HttpResponseRedirect('AddressTableMaintain/');
    else:
        form = CustomerForm()

    return render(request, 'CustomerInfo.html', {'form': form})

# Create your views here.

the form page like below:
calc/templates/CustomerInfo.html:

{% extends 'base.html' %}

{% block title %} Add and Show Customer details {% endblock %}

{% block content %}
<style>
table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
}
</style>
<form action="{% url 'show_save_customer' %}" method="post">
{% csrf_token %}
<table width="50%" align="center">
    <tr>
        <td>Customer ID</td>
        <td>
            {{ form.customer_id }}

        </td>
    </tr>
    <tr>
        <td>First Name</td>
        <td>
            {{ form.first_name }}

        </td>
    </tr>

    <tr>
        <td>Last Name</td>
        <td>
            {{ form.last_name }}
        </td>
    </tr>
    <tr>
        <td colspan="2" align="center"><input type="submit" value = "OK" /></td>
    </tr>
</table>
</form>
{% endblock %}

After I fill out some data and click the OK button, I always the error mentioned at the beginning, can someone tell me what's wrong with my code?

Upvotes: 1

Views: 1254

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 600059

Indeed, forms do not expose their fields as attributes. You need to access the data via form.cleaned_data - which you should do after you have called form.is_valid().

    form = CustomerForm(request.POST)
    cursor = connection.cursor()
    # check whether it's valid:
    if form.is_valid():
        query = """ insert into customers (first_name, last_name) values (%s, %s) """
        cursor.execute(query, [form.cleaned_data['first_name'], form.cleaned_data['last_name']])
        return HttpResponseRedirect('AddressTableMaintain/');

Note also however, unless you have a really good reason you should avoid raw SQL queries and use the Django model layer for your queries. In this case a ModelForm would be even more suitable as it would create and save the instance for you with a simple form.save().

Also note, you do anything on the form to show errors when the form is invalid. There are various ways of doing this, but at the very least you should put {{ form.errors }} in there somewhere.

Upvotes: 2

Related Questions