Python Flask + AJAX how to update div variable without reloading page - javascript

I have this example where I am trying to see if I have a record in my database to see whether or not this Triggered variable in my <div class="container-fluid"> is true or false. I have it that I can POST the page just fine but I am wondering if you could show me how I can get AJAX to constantly check if it has been triggered and change the variable Triggered inside that div without refreshing anything else.
HTML
**<div class="container-fluid" id="trigger-container">**
<h1>Incubator Controller</h1>
<div class="col-sm-4" style="background-color:lavender;">
{% if Triggered == "True" %}
<span class="badge badge-pill badge-success">ALL CLEAR</span>
{% else %}
<span class="badge badge-pill badge-danger">PROXIMITY ALERT</span>
{% endif %}
</div>
and the python flask side looks like this:
#app.route('/update', methods=['POST','GET'])
def Updater():
Node = DAO.Pull_Node_Status(NodeID)
Triggered= Node.Triggered[0]
return render_template('Controller.html',Triggered=Triggered)
I know that I will need to use setInterval to call a javascript function.. but I am having a hard time piecing it together. This is the most simplest example that I can think of. I would like to be able to update multiple things constantly without refreshing the page and losing everything.
HTML script portion
<script>
function UPDATETriggerDiv() {
$.get('/updateTrigger',
function(data){
const parsed = JSON.parse(data)
something to do here with (parsed.Triggered);
g2.refresh(parsed.currentHumidity);
};
)
};
setInterval(function () {
UPDATETriggerDiv();
return false;
}, 2500);
</script>
Any help would greatly be appreciated!

If parsed.Triggered is boolean then you can set the Incubator Controller with an if/else statement.
var html = '<span class="badge badge-pill ';
if (parsed.Triggered){
html += 'badge-success">ALL CLEAR</span>';
}
else{
html += 'badge-danger">PROXIMITY ALERT</span>';
}
$("#trigger-container h1 + div").html(html);

Related

Django: Writing JavaScript inside template vs loading it

I am using JavaScript to add comment without refreshing the page. When I am using JavaScript inside the template it is working perfectly fine but if I am writing the JavaScript to a file and loading the file inside the template then it is not displaying the name of the person who wrote the comment (It is displaying the comment fine). Below is the JavaScript I used inside the template:
function create_comment(event,div_id,form_id,commentinsert_id) {
event.preventDefault();
var text_id = '#'.concat(div_id,' ','#comment-text')
var slug_id = '#'.concat(div_id,' ','#post_slug')
var appenddiv_id = '#'.concat(div_id)
comment_count ++;
var divcommentinsert_id = 'inserted_comment-'.concat(comment_count.toString())
$.ajax({
url : "create_comment/", // the endpoint
type : "POST", // http method
data : { text : $(text_id).val(), post_slug: $(slug_id).val(),},
// handle a successful response
success : function(json) {
div.innerHTML = `
<div id = `+divcommentinsert_id+` class="card-footer">
<div class="row">
<div>
<img src="{{user.profile.profile_picture.url}}" alt="" width="40" height="40">
</div>
<div class="col-md-8">
<b style="color:rgb(240, 0, 0);"> {{user.first_name}} {{user.last_name}}</b>
<br>
`+json.text+`
<a onClick="edit_comment('`+json.slug+`','`+divcommentinsert_id+`','`+json.text+`')"><i class="fa fa-edit"></i></a>
<a onClick="delete_comment('`+json.slug+`','`+divcommentinsert_id+`')"><i class="fa fa-trash-o"></i></a>
</div>
</div>
</div>`;
document.getElementById(commentinsert_id).appendChild(div);
document.getElementById(form_id).reset();
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
$('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
" <a href='#' class='close'>×</a></div>"); // add the error to the dom
console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
}
});
};
In the above code <b style="color:rgb(240, 0, 0);"> {{user.first_name}} {{user.last_name}}</b> is used to display the name. It is displaying name of the person who added the comment but when I copy the same function to comments.js file and load the file like <script src="{% static 'scripts/comments.js' %}"></script> then its not displaying the name instead it is displaying {{user.first_name}} {{user.last_name}}. I am using this javascript in several pages, I thought it is best to write to file and load the file instead of writing the same script in every page. Can someone help me with this?
{{ dictionary.key }}, etc in a template is how you use variables with the django template engine.
A static javascript file is not a template. It isn't processed by the django template engine.
Put the values you need in your html (through the template engine), access them from JS.
Basic ideas:
Create a JS variable (eg: <script>var user_full_name = "{{ user.user_name }} {{ user.last_name }}"</script>), use user_full_name inside the ajax sucess callback.
Put the values inside some html element (eg: <input type="hidden" id="user_name" value="{{ user.user_name }}">) and get it with JS/jQuery $("#user_name").val().
edit: added missing closing double quote to the user_full_name declaration.

Using django-select2 for a dropdown list with pictures

I'm trying to take another approach for the problem I desribed below making use of django-select2 module.
Django choicefield using pictures instead of text not displaying
I have a django model which looks like:
My model looks like:
class MyPicture(models.Model):
name = models.CharField(max_length=60,
blank=False,
unique=True)
logo = models.ImageField(upload_to='logos')
def __str__(self):
return self.name
I would like to create a drop down looking like
source: http://select2.github.io/select2/
where essentially I have a big picture on the left (corresponding to what I called logo) and some text on the right (corresponding to name).
My form looks like:
from django_select2.forms import Select2MultipleWidget
class MyPictureForm(forms.Form):
pictures = forms.ModelChoiceField(widget=Select2MultipleWidget, queryset=MyPicture.objects.all())
My view looks like:
def mypicture(request):
form = MyPictureForm(request.POST or None)
if form.is_valid():
#TODO
return render(request, 'myproj/picture.html', {'form': form})
and finally, my hmtl (where something is wrong):
{% load staticfiles %}
<head>
{{ form.media.css }}
<title>In construction</title>
</head>
<form action="{% url 'mypicture' %}" method="post">
{% csrf_token %}
<select id="#e4" name="picture">
{% for x in form.pictures.field.queryset %}
<option value="{{ x.id }}"><img src="{{ MEDIA_URL }}{{ x.logo.url }}" height=150px/></option>
{% endfor %}
</select>
<br>
<br>
<input type="submit" value="Valider" class="btn btn-primary"/>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
function format(x) {
if (!x.id) return x.name; // optgroup
return "<img src=" + x.logo.url + "/>" + x.name;
}
$(document).ready(function () {
$("#e4").select2({
formatResult: format,
formatSelection: format,
dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
escapeMarkup: function (m) { return m; } // we do not want to escape markup since we are displaying html in results
});
});
</script>
{{ form.media.js }}
</form>
Unfortunately I'm not good enough to tell whether my error is in the javascript or in the loop. When I right click to get the source code, the options are properly set. So I must not be to far from the answer.
It might be trivial for those of you with more javascript experience than me.
Thanks for your help!!
Best:
Eric
I think (most) browsers don't allow anything inside an <option>-tag besides plain text.
This is what Mozilla says about the allowed content of <option>-tags:
Permitted content: Text, possibly with escaped characters (like
é).`
source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option
Not sure if you can set something as a background though.

How to refresh a part of the DOM HTML when querying a foreign django view

Hello Awesome People!
So many questions on StackOverflow are about "How to refresh dom via jquery (from the same view/url)" It's not what I'm looking for.
With a website that large of its parts are running with ajax, I wonder how to refresh a part of the HTML DOM when querying a foreign django view.
Let me be clearer with some examples:
I have that view that sends all_users to template
def usersList(request):
all_users = User.objects.all()
return render(request,'administration/users-list.html',{'all_users':all_users})
In the template I loop through all_users... The 2nd <span> reflects the activation state of the user
{% for u in all_users %}
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
{% endfor %}
With jquery, I send a request to a specific view responsible only to activate or deactivate the account of the user. We can activate/deactivate user in many parts of the website, that's why I do so in a different view.
Here's the view:
def deactivateUser(request):
user = request.user
if user.has_perm('is_admin') and request.is_ajax() and request.method == 'POST':
id_user = request.POST.get('id')
targeted_user = get_object_or_deny(User,id=id_user)
# get_object_or_deny is my own function
it will get the object or raise PermissionDenied otherwise
if targeted_user.is_activate:
targeted_user.is_activate = False
state = 'deactivated'
else:
targeted_user.is_activate = True
state = 'activated'
targeted_user.date_update_activation = NOW() # own function
targeted_user.save()
return JsonResponse({'done':True,'msg':'User successfully %s' %s state})
# Here we return a JsonResponse
raise PermissionDenied
So now, how can I refresh the Dom with following jquery stuff to get the current state of each user
$(document).on('click','.btn-circle',function(){
var id = $(this).data("id");
$.ajax({
url:'/u/de-activate/?ref={{ request.path }}',
type:'post',
data:{
csrfmiddlewaretoken:"{{ csrf_token }}",
id:id,
},
success:function(response){
$("#user_"+id+"_state").replaceWith($("#user_"+id+"_state",response));
if(response.created) alert(response.msg);
},
error:function(){
alert("An error has occured, try again later");
}
});
});
Note that all_users is required to loop through. deactivateUser() return a Json response, even though it doesn't returned it, it will not matter.
You can send http response, not json.
First, just move your html that want to change. in this situation,
{% for u in all_users %}
<div id="user-part">
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
</div>
{% endfor %}
Then save it i.e. user_part.html
Second, make your view return HttpResponse with that html, and context. You can use either HttpResponse or render_to_response. I recommend render_to_response.
context = {
'all_users': all_users,
}
return render_to_response(
'path_to/user_part.html',
context=context,
)
Third, you just change script for replacing your html.
success: function(response){
$('#user-part').html(response);
prevent();
}

Django : combine variable and HTML id in template

I'm looking for a way to "concatene" a django object list (get via the get_queryset in the views.py) with a Javascript variable. then concatene them to a field of a model object.
My model is a blog post, and contains the post_title field (a charfield).
In my index.html, I have a pager button with id="1" or id="2" corresponding to the index of the page and a onClick="displayPostContentOnPageButtonCliked(this.id)" attribute.
My index.html retrieve all post objects in a context_object_name called all_post_by_date.
In my index.html, I want to display on alert dialog the post title corresponding to the button clicked, something like:
<script>
function displayPostContentOnPageButtonCliked(page_button_clicked_id){
var all_posts_by_date = "{{all_posts_by_date.page_button_clicked_id.post_title}}";
alert(all_posts_by_date);
}
</script>
But this doesn't work. I tried to add filter or create my own filter (called get_index, but only manage to get like: all_posts_by_date|get_index:page_button_clicked_id and not be able to combine the .post_title part.
My question is: how to get {{all_posts_by_date.page_button_clicked_id.post_title}} to work, and alert "Title of post 3" when the button 3 is clicked ?
Thank u !
Two solutions for you: (1) send in the data you want to your JS function in the call to the JS function.
<script>
function showPostTitle(post_title){
alert(post_title);
}
</script>
. . .
{% for x in all_posts_by_date %}
<div id='blog-post-{{ x.id }}' on-click="showPostTitle('{{ x.post_title }}')">
. . .
{% endfor %}
Or you can just serialize the data yourself for later use:
<script>
var titles = [];
{% for x in all_posts_by_date %}
titles.push('{{ x.post_title }}');
{% endfor %}
function displayPostContentOnPageButtonCliked(nId) {
var title = titles[nId - 1];
alert(title);
}
</script>

Django: Referencing Views List in Java Script?

So I'm working with Django on a website that I am playing around with, and have been trying to research how I could get the following list in my views.py and be able to reference it in my javascript? I'm working on creating an ajax call and the tutorials I am coming accross are a bit confusing.
#lines 6 - 8 of my code.
def catalog_home(request):
item_list = item.objects.order_by('name') #item is the model name
note: the item model containts a name, description, overview and icon column.
Is it possible for me to use the list above (item_list) and be able to write a javascript function that does something similar to this? :
$(document).ready(function() {
$("#showmorebutton").click(function() {
$("table").append("<tr></tr>");
for (var i = 0; i < 3; i++) {
var itemdescription = item.description;
var itemName = item.name;
var icon = item.icon;
$("table tr:last").append(generateCard(itemName,
itemdescription,
icon));
}
function generateCard(itemNameC, itemdescriptionC, iconC) {
var card = "<td class='tablecells'><a class='tabletext' href='#'><span class='fa "
+ iconC
+ " concepticons'></span><h2 class='header'>"
+ itemNameC
+ "</h2><p>"
+ itemdescripionC
+ "<span class='fa fa-chevron-circle-right'></span></p></a></td>";
return card;
}
I don't mean to crowd source the answer to this, I just would appreciate any feedback/advice for me to handle this task, as I am fairly new to coding.
You should absolutely be able to do this. The trick is to understand Django templates. You showed part of the view but you will need to render to a template. Inside the template, you can just do something like
HTML code for page goes here (if you're mixing js and html)
<script>
var items = [{% for d in data %}
{% if forloop.last %}
{{ d }}
{% else %}
{{ d }},
{% endif %}
{% endfor %}];
// code that uses items
</script>
Note there's a little bit of work required to make sure you have the right # of commas [taken from this SO answer and your code should handle the case where the array is empty.
Alternatively, you could do an ajax call from static javascript to your django server using something like django rest framework to get the list of items as a json object.

Categories

Resources