How to display django queryset values in templates using javascript - javascript

I am trying to display list of names from a django queryset using , Here is my code
def vfunc(request):
context={}
bats = Bat.objects.all().order_by('-id')
context['bats'] = bats
[each.batname for each in bats] # Gives all the batnames.
return render(request, 'bat.html', context)
I want to display batnames on template
$(function() {
//This works when I hardcode the values
var batData = [{
"bat":"batname1", //hardcoded & displayed in 1st row
}, {
"bat":"batname2", //hardcoded & displayed in 2nd row
}];
$("#CleanDatasNames").dxDataGrid({
dataSource: batData,
...
...
}
I am tried something like var batData = [{"bat":"{{bats|join:', ' }}"] but it is displaying obj1,obj2 in same row,I also tried to loop through but failed , any help will appreciated.

This way you can work with js:
$(function() {
//This works when I hardcode the values
var batData = [
{% for bat in bats %}
{
"bat":"{{bat}}",
}
{% if forloop.counter != bats|length %} // dynamically checking for last element
,
{% endif %}
{% endfor %}
];
$("#CleanDatasNames").dxDataGrid({
dataSource: batData,
...
...
}

Related

How do i create and use variables in django

New to Django and its templates.
I'm trying to set a variable given a specific situation, and that part I think ill be able to do, the code below isn't the exact conditions its just there as a demo. The part im stuck on is how do i create a variable name, and then use that name variable elsewhere. Such as within a div or within a method or anywhere else within the html file, and withing different <Script> tags to run methods and for really any purpose.
demo scenario :
{% for row in table.rows %}
{% if row == 2 %}
{% var name = row.name %}
{% endif %}
{% endfor %}
{% if name %}
<div>{{name}}</div>
{% endif %}
my actual code Im trying to implement:
<script type="text/javascript">
function map_init_basic(map, options) {
var markerClusters = L.markerClusterGroup({ chunkedLoading: true });
{% for row in table.rows %}
var x = "{{ row.cells.x }}"
var y = {{ row.cells.y }}
var m = L.marker([y, x])
m.bindPopup("{{row.cells.first_name}} {{row.cells.last_name}} <br>{{row.cells.chgd_add}}");
m.on("click" , ()=>{
//console.log(`${first_name} ${last_name}`)
{% var first_name = {{row.cells.first_name}} %}
})
//changed row.cells.chgd_add to row.cells.Chgd_add to make sure its matching the table
markerClusters.addLayer(m);
{% endfor %}
markerClusters.addTo(map);
}
{% if first_name %}
console.log("{{first_name}}");
{% endif %}
</script>
Django templates are intended to render html but you are trying to render javascript. It can work but the way you are trying to do it is not a good practice; very soon you won't be able to maintain your code.
If you want to pass data directly from python/django to javascript, an accceptable way to do so is to put the data in a dictionary, translate it to a json string and have it set to a var in your javascript.
in a view:
data = dumps(some_dictionary)
return render(request, 'main/template.html', {'data': data})
in the template:
<script>
var data = JSON.parse("{{data|escapejs}}");
</script>
https://docs.djangoproject.com/fr/3.1/ref/templates/builtins/#escapejs
Alternative: You can use django to generate a widget with data attributes and have a javascript operating on this widget and do whaterever needs to be done.

Making a Javascript click function for model objects formatted in Django Tables2 that shows related divs

I'm trying to make a Javascript function involving a django-tables2 table featuring model objects that will show relevant information when clicked. Here is the relevant code:
models.py
class Student(models.Model):
student_id = models.CharField(max_length=128, unique=True, null=True, blank=True)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
ssn = USSocialSecurityNumberField(null=False)
gender = models.CharField(max_length=128, choices=GENDER_CHOICES)
country = CountryField(default='US', blank=True)
primary_phone = models.CharField(max_length=128)
email = models.EmailField(max_length=254, validators=[validate_email])
background = models.CharField(max_length=128, choices=BACKGROUND_CHOICES)
location = models.CharField(max_length=128, choices=LOCATION_CHOICES, default='south_plainfield')
created_at = models.DateTimeField(null=True, auto_now_add=True)
tables.py
class StudentListTable(tables.Table):
name = tables.TemplateColumn('''{{ record.first_name }} {{ record.last_name }}''', verbose_name=u'Name')
manage = tables.TemplateColumn('''Update / Delete''')
assign = tables.TemplateColumn('''Courses / Employment / Counselor / Show''')
class Meta:
model = Student
fields = ('student_id', 'name', 'gender', 'ssn', 'email', 'primary_phone', 'created_at', 'manage', 'assign')
row_attrs = {
'id': lambda record: record.pk
}
attrs = {'class': 'table table-hover', 'id': 'student_list'}
views.py
def all_My_Student(request):
student_list = Student.objects.order_by('-created_at')
table = StudentListTable(student_list)
RequestConfig(request).configure(table)
return render(request, 'students/all_my_student.html', {'table': table, 'student_list': student_list})
all_my_student.html
{% block main_content %}
<div class="box box-primary" id="student_list_table">
{% if table %}
{% render_table table %}
{% endif %}
</div>
{% for student in student_list %}
<div class="detailed" id="{{ student.id }}">
{{ student.first_name }} {{ student.last_name }}
</div>
{% endfor %}
{% endblock %}
{% block custom_javascript %}
<script>
$(document).ready(function()
{
$('.detailed').hide();
}
);
</script>
{% endblock %}
What I want to do is make a Javascript function that's basically like this: As you can see, the "detailed" class divs are hidden from the start. When you click on a row in the model object table, the "detailed" class div with an id that matches that of the row (or basically corresponds with the same model object in both the table loop and the second loop) will show, and the rest will still be hidden. I hope that it's clear.
As a sidenote, if the queryset used in the table is the same as student_list there is no need to pass student_list separately to the template context, you can just use table.data.
I would hide the <div class="detailed"> blocks using CSS, and not using JavaScript, as if you do use JavaScript, they might be visible for a slight moment when the page loads.
You should try to avoid adding id attributes to too much html elements. In your example, you add the student id as an id attribute to both the table <tr>'s and the <div class="detailed"> elements. The HTML spec requires ID's to be unique in the whole document, so if you want to use them, make sure they are unique.
It's better to use data attributes. In the example below, I added the attribute data-student-id to both the table row and the <div class="detailed"> element. You can now select div[data-student-id="12"] to get the details div element for student with id = 12:
# table.py
class StudentListTable(tables.Table):
name = tables.TemplateColumn('''...''', verbose_name=u'Name')
manage = tables.TemplateColumn('''....''')
class Meta:
model = Student
fields = ('student_id', 'name', 'gender', 'ssn', 'email', 'primary_phone', 'created_at', 'manage', 'assign')
row_attrs = {
'data-student-id': lambda record: record.pk
}
attrs = {'class': 'table table-hover', 'id': 'student_list'}
{# django template #}
<style>
.detailed {
display: none;
}
</style>
{% for student in table.data %}
<div class="detailed" data-student-id="{{ student.id }}">
{{ student.first_name }} {{ student.last_name }}
</div>
{% endfor %}
{% block custom_javascript %}
<script>
$(document).ready(function() {
$('#student_list tr').on('click', function () {
var student_id = $(this).data('student-id');
$('div[data-student-id="' + student_id + '"]').show();
});
});
</script>
{% endblock %}
Alternatively, you could add the required data to data- attributes of the table and create the details view in JavaScript. That maybe would make the generated HTML a bit smaller.

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>

calling function with ajax, part working but part not working

Sorry if the title isn't very clear. I have search engine that works with ajax function. Right now if I type t in a search box, the tags that contain the word t shows up(ex if I type t, then test shows up) but thing is after I delete the word t all the tags show up in the result part. Does this make sense? if I'm not clear I'll post the picture. I'm not sure why or how to fix this.
Here;s my code.
<h3>Search</h3>
{% csrf_token %}
<input type="text" id="search" name="search" onkeyup="handle_keyup()"/>
<ul id="search-results">
</ul>
Here I can't delete search-results as this will show the search results but on this section when nothing is typed still all the tags show up. (it only shows all when I finish using search bar)
my ajax
function handle_keyup() {
$.ajax({
type: "POST",
url: "/search/",
data: {
'search_text' : $('#search').val(),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: 'html'
});
};
function searchSuccess(data, textStatus, jqXHR)
{
$('#search-results').html(data);
}
problem is probably occurring from up there, but I'll post the back end as well. This is python django framework.
def search_titles(request):
# categories = SearchQuerySet().autocomplete(content_auto=request.POST.get('search_text', ''))
categories = Category.objects.filter(name__icontains=request.POST.get('search_text', ''))
return render_to_response('main/ajax_search.html', {'categories' : categories})
ajax_Search.html
{% if categories.count > 0 %}
{% for category in categories %}
<li>{{ category.name }}</li>
{% endfor %}
{% else %}
<li>None to show!</li>
{% endif %}
thanks in advance
This is happening because when the user "deletes" the word, your handle_keyup function is fired, sending a search request of '' to the server.
The server then looks for the empty string '' in the category names and finds it in all of them.
One approach is for the server to check if the search text is empty, and if it is, return nothing. Something like:
def search_titles(request):
txt = request.POST.get('search_text', '')
if txt:
categories = Category.objects.filter(name__icontains=txt)
else:
categories = []
return render_to_response('main/ajax_search.html', {'categories' : categories})

New forms - embedding a collection of forms - Symfony2

I'm doing the same as explained here: http://symfony.com/doc/current/cookbook/form/form_collections.html
But in my case I want to add new "tags" not manually with clicking on a link, but automatically. I give to my template an array with items and for each of this items I want to add a new form - the number of items should be equal to the number of forms.
If it's possible, I'd prefer a solution like this:
{% for i in items %}
{{ i.name }} {{ form_widget(form.tags[loop.index0].name) }}
{% endfor %}
But how to automatically create objects in the controller, too? It tells me that there is no obeject with index=1, and yes - there isn't, but isn't there a way to create them automatically and not need to create for example 10 empty objects of the same kind in my controller? :(
Another thing I was thinking was something like this:
{% for i in items %}
<ul class="orders" data-prototype="{{ form_widget(form.orders.vars.prototype)|e }}">
{{ i.name }} and here should be a field from the form, for example tag.name
</ul>
{% endfor %}
I suggest that the js given in the cookbook should be changed to do this, but I'm not good in js and my tries didn't do the job.
I tried putting this in the loop:
<script>
addTagForm(collectionHolder);
</script>
and this in a .js file:
var collectionHolder = $('ul.orders');
jQuery(document).ready(function() {
collectionHolder.data('index', collectionHolder.find(':input').length);
function addTagForm(collectionHolder) {
var prototype = collectionHolder.data('prototype');
var index = collectionHolder.data('index');
var newForm = prototype.replace(/__name__/g, index);
collectionHolder.data('index', index + 1);
var $newFormLi = $('<li></li>').append(newForm);
}
});
Assuming that your main class has addTag($tag) method, you can add different 'new' tags to it.
In class Task
public function addTag($tag){
$this->tags[]=$tag;
return $this;
}
In your Controller (assuming 10 tags here)
$task=new Task();
for($i=0;i<10;i++){
$task->addTag(new Tag());
}
$form->setData($task);
In your view
{% for tag in form.tags %}
<ul class="orders">
<li>{{ form_widget(tag.name) }}</li>
</ul>
{% endfor %}
If you don't need the manually click, you can remove the JavaScript part.

Categories

Resources