dynamic JQuery view in django - javascript

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.

Related

changed tab value but not reflect in page?

I'm using ajax to seek a solution to dynamic update data-value in div and reflect effect in HTML.
the data-value come from the backend flask and sql DB.I know the data-value already be updated since if I refresh the page, the new data-value be reflect in page. Is there a way to achieve this function to real-time auto reflect the effect on web page ? I don't want trigger another form submit to achieve this effect. : )
In short word, the ajax response data success, but it not update the html, so web page didn't reflect the updated value.
thank you !
#app.route("/fetch_bar",methods=['POST'])
def fetch_bar():
result = [{'hostname': 'testaa101.com', 'status': '30'}] ### example data that actually getting from DB.
app_json = json.dumps(result)
return jsonify(app_json)
function bar_progress(){
$.ajax({
url:"{{ url_for('fetch_bar') }}",
type:"post",
dataType: "json",
async: false,
success:function(response){
var response = JSON.parse(response);
var len = Object.keys(response).length;
var bars = document.querySelectorAll("[id=ldBar]");
if (len > 1)
for( var ind = 0; ind < len; ind++){
if (selects[index].value == response[ind].hostname)
bars[index].setAttribute("data-value",response[ind].status);
}}})}
function shadow_progress() {
bar_progress()
setTimeout(shadow_progress, 15000);
}
shadow_progress();
<form id="myform" name="myform" action="{{url_for('show_select')}}" method="post">
{% for entry in entries %}
.....
<td>
<input id="stage" type="button" class="btn-primary" onclick="readTextFile();" name="stage" value="{{entry.stage}}" >
<div id="ldBar" class="ldBar label-center" data-value="0" data-preset="stripe" data-aspect-ratio="none" style="width:100%;display: block;" ></div>
</td>
......
{%endfor %}

load part of the html page when filtering results with ajax

I want to filter a search results using 3 checkboxs. The results are presented in the div with the id=posts_results
<div class="checkbox">
<label><input type="checkbox" id="id1" class="typePost" value="En groupe"> val1 </label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="id2" class="typePost" value="En groupe"> val2 </label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="id3" class="typePost" value="A domicile"> val3</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="id4" class="typePost" value="Par webcam"> val4</label>
</div>
<div id="posts_results">
{% include 'posts/posts_results.html' %}
</div>
<script>
$('.typePost').change(function (request, response) {
var v1=$('#id1').is(":checked")? 1:0;
var V2=$('#id2').is(":checked")? 1:0;
var V3=$('#id3').is(":checked")? 1:0;
var v4=$('#id4').is(":checked")? 1:0;
$.ajax({
url: '/posts/type_lesson/',
dataType: 'json',
type: "GET",
data: {
group: groupChecked,
webcam: webcamChecked,
home: homeChecked,
move: moveChecked,
distance: distance,
},
success: function (object_list) {
$('#posts_results').load("my_page.html", object_list);
alert('after')
}
});
});
<script>
this is my url:
url(r'^filter/$', views.filter, name='filter_type_lesson'),
and this is my view:
def filter(request):
if request.method=='GET':
#as an exemple I'll send all posts
data= PostFullSerializer(Post.objects.all(), many=True)
return JsonResponse(data.data, safe=False)
The filter function excute some filters according to the json sent data, serialize the filtered posts and send them back (in this case I send all the posts as an example).
The results are displayed using a forloop in the div with id "posts_results" and the html is in the file posts_results.html.
The json data are sent but the ajax success function does not update or load the div
and it is also possible to stay
I like to stay away from raw POST data as much as possible and let the forms API do the heavy lifting. You can do what you have already with a lot less code in a much more secure way.
Make a form with four BooleanFields named for the BooleanFields in your model. You can override how they are displayed in the HTML with the label variable.
class TheForm(forms.Form):
my_field = forms.BooleanField(required=False, label="What I want it to say")
my_field2 = forms.BooleanField(required=False, label="What I want it to say 2", help_text="Something else")
my_field3 = forms.BooleanField(required=False, label="What I want it to say 3", help_text="Something else")
Output as <form class="my_form">{% csrf_token %}{{form.as_table}}</form>
Submit it with JS like this:
$('.my_form input[type=checkbox]').change(function(e){
e.preventDefault()
$.post('module/filer/', $('.my_form').serialize(), function(data) {
// Handle data
});
});
When the form is submitted and validated take the cleaned_data attribute and filter your models like this
models = Post.objets.filter(**form.cleaned_data)
This will work because the form fields and named the same as the fields in your model. The same as doing Post.objects.filter(my_field=True, my_field2=True, my_field3=False). Then you can do whatever you want with it. I would use a FormView to do all this:
class MyView(FormView):
form_class = TheForm
def form_valid(self, form):
models = Post.objets.filter(**form.cleaned_data)
data= PostFullSerializer(data, many=True)
return JsonResponse(data.data, safe=False)
Now nothing is going to update the div by itself. It is only created when the HTML is initially requested. In your success function you'll need to append your elements manually like this:
$('.my_form input[type=checkbox]').change(function(e){
e.preventDefault()
$.post('module/filer/', $('.my_form').serialize(), function(data) {
var post_results = $('#post_results').html(''); // Clear out old html
$.each(data, function(item) {
// Create new divs from ajax data and append it to main div
var div = $('<div>');
div.append($('<div>').html(item.my_field));
div.append($('<div>').html(item.my_field2).addClass('something'));
div.appendTo(post_results);
});
});
});
You can also just past rendered HTML through ajax and do $('#post_results').html(data);. Instead of calling json response you would call self.render_to_response on the FormView.
maybe you could try to render the template in your view and then load the rendered data in your div.
Supposing your posts/posts_results.html is some as:
<ul>
{% for post in posts %}
<li> Post: {{post.name }} / Author: {{post.author}} / Date: {{post.created_at}}</li>
{% endid %}
<ul>
In your view, at the moment when you do respective actions, you can render the template and add the html content to the response, ie (based un your current code):
def filter(request):
if request.method=='GET':
json_data = {
"success": False,
"message": "Some message",
"result": "some result",
}
posts = Post.object.all()
template = "posts/posts_results.html"
things_to_render_in_your_template = {
"posts": posts, # you can add other objects that you need to render in your template
}
my_html = get_template(template)
html_content = my_html.render(things_to_render_in_your_template)
# here the html content rendered is added to your response
json_data["html_content"] = html_content
json_data["success"] = True
return JsonResponse(json_data)
Then in your JS, at the momento to check ajsx response, you can add the rendered content into your div
$.ajax({
url: '/posts/type_lesson/',
dataType: 'json',
type: "GET",
data: {
group: groupChecked,
webcam: webcamChecked,
home: homeChecked,
move: moveChecked,
distance: distance,
},
success: function (response) {
# response is the json returned from the view, each key defined in your json_data dict in the view, is a key here too
# now insert the rendered content in the div
$('#posts_results').html(response["html_content"]);
alert('after');
}
});
I suggest you instead of create one by one data to your ajax request, use serialize method of jquery or create a FormData object, also instead of GET, use POST to do your request more safe

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.

knockout js template from javascript file

I'm submitting a form to a php file, which returns some products from the database. I now need to add a knockout template with the returned data. Here is the code:
$("#search-filter-form").submit(function(event) {
// stop form from submitting normally
event.preventDefault();
// get some values from elements on the page:
var $form = $( this ),
url = $form.attr( 'action' );
// Send the data using post
var posting = $.post(url,
{ place: searchFilterViewModel.searchFilterAutoComplete.placeObject,
categories: searchFilterViewModel.categorySelect.selectedCategories
}).done(function(data) {
searchResultsViewModel.allProducts(JSON.parse(data));
for(var x = 0; x < searchResultsViewModel.allProducts().length; x++) {
$("search-results").append();// NEED TO APPEND THE KNOCKOUT TEMPLATE HERE
}
});
});
I want to have a seperate file with the html template. I have created this example file:
product_template.html:
<script type="text/html" id="product-template">
<h3 data-bind="text: allProducts.name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</script>
How do I get that template file to print out, from within the javascript function above?
Store the data in an observable/object, and pass that to the template itself, so it can read it.
You only linked the template file, you need another line to apply data to it, e.g.
<div data-bind="template: { name: 'product-template', data: buyer }"></div>

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

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.

Categories

Resources