AttributeError: 'unicode' object has no attribute 'get' - In Django Forms - javascript

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:
using data=request.POST
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"

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

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.

Related

Using setattr() to update an object instance

I have a model class which has an attribute that refers to django DB objects. I would like to change this attribute using a single view with setattr() which I use to make changes to any attributes for this object.
The problem is, I can't seem to pass an object instance through the stack. I'm not sure if I can even use setattr() for this. Actually I'm not even sure if the problem is with my attempted use of setattr() or something else - please let me know!
Error on POST attempt:
ValueError at /dollhouseupdate/1
Cannot assign "u'Citadel'": "Dollhouse.dh_background" must be a "Background" instance.
Model:
class Dollhouse(models.Model):
dollhouse_name = models.CharField(max_length=100)
user = models.ForeignKey(User)
dh_background = models.ForeignKey(Background)
def __str__(self):
return self.dollhouse_name
Template:
<select id="background-select">
<option value="null">Change Background</option>
{% for background in background_objects %}
<option value="{{ background }}">{{ background.bg_name }} </option>
{% endfor %}
</select>
View:
def dollhouseupdate(request, dollhouseid):
if request.method == 'POST':
workingdollhouse = Dollhouse.objects.get(id=dollhouseid)
if request.POST.get('erase') == "true":
workingdollhouse.delete()
return HttpResponse("Dollhouse deleted!")
else:
data = (request.POST).dict()
for key, value in data.items():
setattr(workingdollhouse, key, value)
workingdollhouse.save()
return HttpResponse("Dollhouse {} saved!".format(workingdollhouse.dollhouse_name))
Javascript:
//change dollhouse background
$("#background-select").change(function() {
if($("#background-select").val() != null) {
var dollhouseid = workingDollhouse;
var dh_background = $("#background-select").val()
console.log("changing background to " + dh_background);
$.ajax("http://127.0.0.1:8000/dollhouseupdate/"+dollhouseid, {
type: 'POST',
data: {
dh_background: dh_background,
}
})
.done(function(response){
console.log("The request is complete!");
console.log(response);
window.location = "http://127.0.0.1:8000/";
})
.fail(function() {
console.log("Sorry, there was a problem!");
})
};
});
You are passing the object id in the POST variable, not the actual object itself (you can't do it anyway). Either change the following part
data: {
dh_background: dh_background,
}
to
data: {
dh_background_id: dh_background,
}
or get the object instance using the id in your view code.
As the error says, the Dollhouse.dh_background attribute must be an instance of the Background model. You are attempting to set its value to an object of a different type; I think a text string.
type(u'Citadel') is Background # False
Instead, you'll need to put some smarts into the view so that Background instances are retrieved by whatever key you have; then, set the Dollhouse.dh_background attribute to that instance.
if name == 'background':
background_code = post_args[name]
background = Background.objects.get(code=background_code)
workingdollhouse.dh_background = background
Because different POST arguments will refer to different fields, you will need to know what each one refers to and treat them differently. A simple “setattr for each one” won't work.

Unable to get object from Controller to JSP

I am trying to pass an object from Spring Controller to my JSP page and plan to iterate the object in JSP using JSTL. But I am unable to print the object in JSP. From the controller side, the value is sent successfully. I am thinking something is wrong in Javascript or JSP.
Request your valuable inputs. Pls find the code below,
Controller :
#RequestMapping("/changehistory/getSearchHistory.htm")
public ModelAndView getSearchHistory(#ModelAttribute(HISTORY_CRITERIA) HistoryCriteria historyCriteria,ModelMap model) {
ModelAndView mav = new ModelAndView("changehistory/changeHistory_new");
List<HistoryCriteriaResult> result=new ArrayList<HistoryCriteriaResult>();
result=changeHistoryService.getHistory(historyCriteria);
mav.addObject("historyCriteriaResult", result);
return mav;
}
JSP:
<div class="ItemListNavBoxLeft" style="margin-top: -2px; padding-left: 20px;"
id="accordianRefreshBtn">
<div class="OrangeFB" style="width: auto; " onclick="RP.getSearchHistory()">
<div class="Q2"><div class="Q8"><div class="Q4"><div class="Q6"><div class="Q1"><div
class="Q3"><div class="Q7"><div class="Q9"><div class="Q5">
<spring:message code='label.button.history'/>
</div></div></div></div></div></div></div></div></div>
</div>
</div>
<div id="changeHistorydiv" style="display:<c:choose><c:when
test='${fn:length(historyCriteriaResult) > }'>block</c:when>
<c:otherwise>none</c:otherwise></c:choose>;">
<ul class="FormBody" style="padding-left:150px;">
<li class="FormFieldTitle"></li>
id="RP.changeHist"
name="changeHist">
<c:forEach items="${historyCriteriaResult}"
var="HCList">
${HCList.code}
${HCList.name}
</c:forEach>
</ul>
</div>
JS :
RP.getSearchHistory = function() {
dojo.xhrPost({
url : "/RMT/rateplan/getSearchHistory.htm?",
timeout : 100000,
load : function(content) {
var iList = content['result'], i;
HCList.options.length = 0;
for (i = 0; i < iList.length; i++) {
HCList.options[HCList.options.length] = new Option(iList[i].name, iList[i].code);
}
},
error : function(error) {
rmt.ErrorMessage.show(error);
}
});
}
You cannot access Java variable HCList inside your JavaScript code, you have two options:
First you could return result in another JSP page and in this case you don't need to do getSearchHistory Ajax call, you can do this by defining another controller method in your controller class, check a form submission example here, check how the controller class is implemented with two methods each one corresponded to a unique JSP file
Second, If you want return historyCriteriaResult in an AJAX request, then you must convert it to JSON format, so you need to change your Java method to something like this:
#RequestMapping("/changehistory/getSearchHistory.htm")
public #ResponseBody List<HistoryCriteriaResult> getSearchHistory(#ModelAttribute(HISTORY_CRITERIA) HistoryCriteria historyCriteria) {
List<HistoryCriteriaResult> result=new ArrayList<HistoryCriteriaResult>();
result=changeHistoryService.getHistory(historyCriteria);
return result;
}
And in your JavaScript method you would parse the JSON response like this:
handleAs: "json", // This force the response to be treated as JSON
load : function(content) {
alert(content.HistoryCriteriaResultList[0].code);
alert(content.HistoryCriteriaResultList[0].name);
.
.
// or append it to any div you want
}
Note: If you are using Spring 3 or above, you need to add Jackson JSON Parser to you project classpath

Grails RemoteFunction creates bad javascript

I am taking over a project from an engineer that left my company, and am having to quickly come up to speed on Grails, so if this is a noob question, well, I'm a noob.
In one of one of my GSP files, I've got a remoteFunction call in the middle of a javaScript function:
function fnCreateEntitiesPerForceChart() {
var interval = $("#entitiesPerForceTimeIntervalSelect").val();
var url = '${createLink(controller: 'federation', action: 'createEntitiesPerForceChart')}?interval='+escape(interval);
$("#entitiesPerForceChart").attr("src", url);
${remoteFunction(controller: 'federation',
action: 'getEntitiesPerForceTable',
params: '\'interval=\'+interval',
onSuccess: 'fnUpdateEntitiesPerForceTable(data,textStatus)')};
}
That remoteFunction call is being sent to the client as:
try{DojoGrailsSpinner.show();}catch(e){} dojo.xhr('Get',{content:{'interval='+interval}, preventCache:true, url:'/FederationReporter/federation/getEntitiesPerForceTable', load:function(response){ fnUpdateEntitiesPerForceTable(data,textStatus); }, handle:function(response,ioargs){try{DojoGrailsSpinner.hide();}catch(e){} }, error:function(error,ioargs){try{DojoGrailsSpinner.hide();}catch(e){} } });;
Which is causing a error:
SyntaxError: missing : after property id
...){} dojo.xhr('Get',{content:{'interval='+interval}, preventCache:true, url:'/Fed...
federation (line 400, col 60) (which is the bolded '+' before the second 'interval'
What am I missing?
Dojo content should be a key-value pair.
{content:{'interval': interval}

dynamic JQuery view in django

my jquery looks like this:
$('#id_start_date_list').change(
function get_time()
{
var value = $(this).attr('value');
alert(value);
var request = $.ajax({
url: "/getTime/",
type: "GET",
data: {start_date : value},
dataType: "json",
success: function(data) {
//Popluate combo here by unpacking the json
}
});
});
my view.py looks like this:
def getTime(request):
if request.method == "GET":
date_val = request.GET.get('start_date')
format = '%Y-%m-%d'
sd = datetime.datetime.strptime(date_val, format)
sql_qw = MeasurementTest.objects.filter(start_date = sd)
results = [{'start_time': str(date.start_time), 'id_start_time':date.start_time} for date in sql_qw]
print results
*****json_serializer = serializers.get_serializer("json")()
response_var= json_serializer.serialize(results, ensure_ascii=False, indent=2, use_natural_keys=True)*****
return HttpResponse(response_var, mimetype="application/json")
my html page looks like this:
html>
<head>
<title>date Comparison</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="/example/" method="post" align= "center">{% csrf_token %}
<table align = "center">
<tr>
<th><label for="start_date_list">Date 1:</label></th>
<th> {{ form.start_date_list }} </th>
</tr>
<tr>
<th><label for="start_time_list">time:</label></th>
<th><select name="start_time_list" id="start_time_list"></th>
<option></option>
</select>
<th></th>
<div id = "log"></div>
</tr>
<tr align = "center"><th><input type="submit" value="Submit"></th></tr>
</table>
</form>
</body>
</html>
As you can see i am getting the value from the select box and i am performing operations on the database and retreiving values and storing it in the json object.
There are two parts that i am totally blind.
First is the json object, where i am not sure whether the results are getting stored in the response_var object.
The second is that, i am not sure how to get values from a json object onto the new list of "start_time_list"
In detail: have i have done anything wrong in the json object initialisation. I have tried to print the respose_var, but it seems not to be printed on the console. Am i using the right syntax? and can someone tell me how to view the values stored in the json object in the view.py
In the similar way, how do i perform operations on the jquery side, to extract values from a json object and how to assign the values of a json object onto a list box by means of sample code and possible solutions.
To convert the results to json, use simplejson:
from django.utils import simplejson
def getTime(request):
if request.method == "GET":
date_val = request.GET.get('start_date')
format = '%Y-%m-%d'
sd = datetime.datetime.strptime(date_val, format)
sql_qw = MeasurementTest.objects.filter(start_date = sd)
results = [{'start_time': str(date.start_time), 'id_start_time':date.start_time} for date in sql_qw]
print results
response_var = simplejson.dumps(results)
return HttpResponse(response_var, mimetype="application/json")
To access the json object in your javascript, take a look at your ajax request. The success callback is being passed a parameter, data in this case. That is the variable containing the server response. So, to access the first element of the resultant array (for instance), you could:
var request = $.ajax({
url: "/getTime/",
type: "GET",
data: {start_date : value},
dataType: "json",
success: function(data) {
//Popluate combo here by unpacking the json
data[0]; // This is the first element of the array sent by the server
}
});
Lastly, to modify the html, jQuery provides plenty of methods, such as html or append. It's worth taking a look at the doc. So if you want to build a collection of options for a select tag, you should iterate over the result set using the javascript for loop, jQuery each method or similar, construct the options (this can be accomplished either concatenating strings or creating DOM elements, which I think is the best solution, as it performs better) and insert them in the html with one of the methods previously mentioned.

JQuery-Ui Autocomplete not displaying results

I am trying to display autocomplete results for a list of managers. I have the following code:
Application.js
function log(message) {
$( "<div/>" ).text( message ).prependTo("#log");
}
$("#managers").autocomplete({
source : function(request, response) {
$.ajax({
url : "/managerlist",
dataType : "json",
data : {
style : "full",
maxRows : 12,
term : request.term
},
success : function(data) {
var results = [];
$.each(data, function(i, item) {
var itemToAdd = {
value : item,
label : item
};
results.push(itemToAdd);
});
return response(results);
}
});
}
});
Project controller
def manager_list
list=Project.all.map{|i|i.manager_user_id}
arr= [].concat(list.sort{|a,b| a[0]<=>b[0]}).to_json
render :json =>arr
end
Routes.rb
match '/managerlist' => 'projects#manager_user_id'
_form.html.erb
<p>
<%= f.label :manager_user_id %><br />
<input id="managers" />
</p>
The following code is fine, I don't recieve no errors in firebug. However when I try to enter a managers name for example James Johnson the name won't appear. I have also tried putting the whole function in the _form.html.erb and wrapped it in tags this didn't work. Is there any idea why this is happening
So I've managed to fix my error, which was because of the ordering of Jquery core and Jquery ui.
I've got the managers to be listed. In the image below.
From the image it can be seen that when I type 'Arm' it brings the entire list of managers, when it should display 'Deshawn Armstrong'. I understand that this is most probably to do with my project controller below
Project controller
def manager_list
list=Project.all.map{|i|i.manager_user_id}
arr= [].concat(list.sort{|a,b| a[0]<=>b[0]}).to_json
render :json =>arr
end
Check the response in the Firebug console and make sure the string is in proper json format for the autocomplete.
It appears that you are just returning an array. The dataType setting in .ajax doesn't convert to json; it's just expecting that format back. If you are not sending json back from your url : "/managerlist", this may be the problem.
Actually, provided your ajax function is working correctly, you could just:
return response(JSON.stringify({ results: results }));
jsfiddle example of JSON.stringify: http://jsfiddle.net/xKaqL/
Based on your new information, you need to add a minLength option to your autocomplete.
$("#managers").autocomplete({
minLength: 2, // 2 or whatever you want
// rest of your code

Categories

Resources