0

I'm trying to use Django Forms with Ajax Calls.

Previously I just used a html form that I could get all the information through request.POST['item']. But I've been thinking about validators, and I would benefit if I switched normal html forms into Django forms.

In my HTML code (the page where the user clicks, and a AJAX calls another view with javascript):

if not request.user.is_authenticated():
    #Tells the user to login if not authenticated 
    return redirect('/webapp/login.html')
else:
    #Get Logger 
    logger = logging.getLogger('views.logger.chartConfigure')
    logger_uuid = uuid.uuid4()
    logger_time = datetime.datetime.now()

    #Log the User
    logger.info("Request in editChart, User:" + str(request.user.username) + ", UUID:" + str(logger_uuid) + ", Time:" + str(logger_time))

    #Forms to use
    chartName = changeChartNameForm(auto_id=False)

    #Put Forms into a context
    context = {'chartNameForm': chartName}

    #Return the context
    return render(request, 'webapp/editChart.html', context)

The Forms that are used is a changeChartNameForm:

#Form for editing chart names
class changeChartNameForm(forms.Form):
    #Only one variable which is called chartName, with label set to ""
    #Since I don't want any labels. I have my own in HTML.
    chartName = forms.CharField(max_length=100, label="")
    #form-control is an extra class that is required by bootstrap 3, and the html id
    #of the form is called chartName
    chartName.widget.attrs['class'] = 'form-control'
    chartName.widget.attrs['id'] = 'chartName'

HTML Code:

<div class="input-group">
    <span class="input-group-btn">
        <button class="btn btn-default" type="button" id="newChartName" >New Chart Name</button>
    </span>
    {{ chartNameForm }}
</div>

The Javascript code:

$.ajax(
{
    type:"POST",
    url:"ajax_postColumnAction/",
    datatype: 'json',
    data:
    {
        'csrfmiddlewaretoken':csrftoken,
        'currentTabSelected':currentTabSelected,
        'currentColumnSelected':currentColumnSelected,
        'action':'changeName',
        'changeNameForm':$('#chartName').serialize()
    },
    success: function(response)
    {
        ...Some logic happens here
    }
}

basically the javascript code will call this view, called ajax_postColumnAction:

#Get the name form, and get the newName
changeNameForm = changeChartNameForm(request.POST['changeNameForm'])
newName = ""
if(changeNameForm.is_valid()):
    newName = changeNameForm.cleaned_data['chartName']

The return is always:

'unicode' object does not have the attribute 'get' at the following line: if(changeNameForm.is_valid())

I have tried the following:

  1. using data=request.POST
  2. using data=request.POST['changeNameForm']

Full Traceback:

Traceback (most recent call last): 
File "C:\Users\Desktop\Dropbox (Personal)\Django\Dashboard_Web\WebApp\views.py", line 738, in ajax_postColumnAction if(changeNameForm.is_valid()): 
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 129, in is_valid return self.is_bound and not bool(self.errors) 
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 121, in errors self.full_clean() 
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 273, in full_clean self._clean_fields() 
File "C:\Python27\lib\site-packages\django\forms\forms.py", line 282, in _clean_fields value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) 
File "C:\Python27\lib\site-packages\django\forms\widgets.py", line 207, in value_from_datadict return data.get(name, None) AttributeError: 'unicode' object has no attribute 'get'

Edit:

When I Do:

print request.POST['changeNameForm']

I get chartName = "some text I typed in the browser"

user1157751
  • 2,427
  • 6
  • 42
  • 73

2 Answers2

1

This part of the error says that data is an unicode string:

return data.get(name, None) AttributeError: 'unicode' object has no attribute 'get'

data needs to be an object. Instead, it is a string, and strings don't have a get() method, and don't have name attributes as the error trace back says.

Try going off of the Django Docs to properly call the AJAX:

https://docs.djangoproject.com/en/1.6/topics/class-based-views/generic-editing/#ajax-example

Aaron Lelevier
  • 19,850
  • 11
  • 76
  • 111
  • Hi, Thanks for your response! Something I don't get is that normal posts are returned by request.POST. In the example: https://docs.djangoproject.com/en/dev/topics/forms/ form = NameForm(request.POST), and that works perfectly. How is my way different? – user1157751 Dec 06 '14 at 02:31
  • According to this other stackoverflow post: http://stackoverflow.com/questions/7335780/how-to-post-a-django-form-with-ajax-jquery User: user931920, indicates that "django code can process the AJAX post the same way it processes other form submissions" – user1157751 Dec 06 '14 at 02:34
  • Plus I'm using function based views, which the webpage is using class based views. – user1157751 Dec 06 '14 at 03:22
0

It seems that a workaround is to construct the form in the view.

I've looked at tenths and hundreds of StackOverFlow posts and Google websites, and non seem to have my problem.

The method is to recreate the form when you get the POST data, since a form uses a dictionary as a constructor.

changeNameForm = changeChartNameForm({request.POST['changeNameForm'].split("=")[0]}):request.POST['changeNameForm'].split("=")[1]})

I know that request.POST['changeNameForm'] returns a string "chartName=someName". I split the string with "=", and I would get someName, and chartName. Hence I would put someName into a dictionary, with the key called chartName.

{'chartName':'someName'}

Hence the form is recreated with the post data and finally passes is_valid.

user1157751
  • 2,427
  • 6
  • 42
  • 73