Adding rows breaks datatable in Django - django

I have a datatable in Django that functions fine when hardcoded, but when I add my Django template tags it breaks. The inspect on the page says: Uncaught TypeError: Cannot set property '_DT_CellIndex' of undefined in jquery.datatables.min.js
This only happens when I have more than one user in the table, or try to add a column in the table with django. Since I will be using multiple datatables in my project, I need to figure out what I'm doing wrong. The datatable JS code I'm using comes from a template, and I'm not sure if the error is in the template code or in my Django template code. So please excuse the long code blocks.
employees.html (django template):
<div class="card-body collapse in">
<div class="card-block card-dashboard">
<button id="addRow" class="btn btn-primary mb-2 js-create-employee"><i class="ft-plus"></i> Add New Employee</button>
<table class="table table-striped table-bordered zero-configuration">
<thead>
<tr>
<th>Name</th>
<th>Username</th>
<th>Roles</th>
<th>Email</th>
<th>Mobile Contact</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for profile in user_profile_list %}
<tr>
{% if not profile.user.is_superuser %}
<td>{{ profile.user.get_full_name }}</td>
<td>{{ profile.user.username }}</td>
<td>
{% for g in profile.user.groups.all %}
<div class="tag tag-default">{{ g.name|split:'_'|title }}</div>
{% endfor %}
</td>
<td>{{ profile.user.email }}</td>
<td>{{ profile.mobile_phone }}</td>
<td><i class="fa fa-pencil"></i> <a href="#" alt="Assign"><i class="fa fa-link"></i><a/> <a href="#" alt="delete"><i class="fa fa-times"></i><a/></td>
{% endif %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Name</th>
<th>Username</th>
<th>Roles</th>
<th>Email</th>
<th>Mobile Contact</th>
<th>Actions</th>
</tr>
</tfoot>
</table>
Datatable instantiation:
$(document).ready(function() {
/****************************************
* js of zero configuration *
****************************************/
$('.zero-configuration').DataTable();
});
Jquery.datatables.min.js and dataTables.bootstrap4.min.js are also used, but those come stock from bootstrap 4. I'm not going to add them here unless needed, and they are minified anyway.

This issues occurs only when data is not available for the table or tags.
You have conditions in template using django templatestag So the number of every <td> element in your table that is a child of a <tr> element doesn't match the number of <th> elements that are a child of the element.
Please make sure you have same number of <td> tag in <tbody> tag.
EDIT:
Maybe {% if not profile.user.is_superuser %} this condition creating this issue. If user is superuser then no <td> tag will create that will not match same number of <th> in <thead>

Related

Populating Table Based on Drop Down Selection

Hi I'm trying to create a table that will show values based on the selected name. For instance if a drop down existed and a value was chosen, the rest of the fields would show the data associated with that chosen value.
<div class="main-items">
<h2>Database</h2>
<div class="card-items">
<table class="main-items-table">
<tr>
<td class="menu-box-tab-items-identifiers">Name:</td>
{% for d in database %}
<td class="menu-box-tab-items" href="/cusip/{{d.company_name}}"><span>{{d.name}}</span></td>
{% endfor %}
</tr>
<tr>
<td class="menu-box-tab-items-identifiers">Item:</td>
{% for d in database %}
<td class="menu-box-tab-items"><span>{{d.item}}</span></td>
{% endfor %}
</tr>
<tr>
<td class="menu-box-tab-items-identifiers">Method of Shipment:</td>
{% for d in database %}
<td class="menu-box-tab-items" href="#6"><span>{{d.method_of_shipment}}</span></td>
{% endfor %}
</tr>
<tr>
<td class="menu-box-tab-items-identifiers">Days:</td>
{% for d in database %}
<td class="menu-box-tab-items" href="#6"><span>{{d.days}}</span></td>
{% endfor %}
</tr>
<tr>
<td class="menu-box-tab-items-identifiers">Location:</td>
{% for d in database %}
<td class="menu-box-tab-items"></span>{{d.location}}</td>
{% endfor %}
</tr>
<tr>
<td class="menu-box-tab-items-identifiers">Country:</td>
{% for d in database %}
<td class="menu-box-tab-items" href="#6"><span>{{d.country}}</span></td>
{% endfor %}
</tr>
</tbody>
</table>
</div>
</div>
Basically, if a drop down menu existed for all the "names", I would want all the other td's to show the data associated with that name. If anyone can help it would be greatly appreciated.
Your options are:
To require the user to submit the form once the first option has been selected and to then refresh the template with related options in the other fields. You would need some code in your forms.py file that can take the provided option and filter the other querysets accordingly.
Use javascript and an AJAX request to dynamically update the other field options once the first field has been selected, here is some useful information:
Django Ajax Jquery Call

Django creating table with hyperlink in cells

I want to display table with basic informations about products, and add hyperlink to cells in column "Product name" after clicking which you will be redirected to more detailed description of product with possibility to edtiing, deleting it etc.
<table class="table table-striped table-dark">
<thead>
<tr>
<th scope="col">Product name</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
{% for element in object %}
<tr>
<td><div class="btn active"><i class="fa fa-check"></i></div></td>
<td>
<a href="{% url 'prod_desc' pk:element.pk %}">
{{element.name|lower|capfirst}}
</a>
</td>
<td>
{{element.price}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
How can I connect hiperlink with product name in table?
In case is there any walk-around solution ?
Is there any restriction about inserting hyperlink in html in general or it's a "Django thing" ?
The problem was in passing primary key of element I used ":" like in dictionary key:value instead of "="
<a href="{% url 'prod_desc' pk=element.pk %}">
{{element.name|lower|capfirst}}
</a>

bootstrap 4 collapse (accordion table) in django

I've posted the code for a table in django templates that is generated dynamically using an array from views.py. I've added a bootstrap4 collapse, that runs when a chevron button is clicked. However, it shows ALL of the hidden collapses instead of just the collapsible data for that given row (see img below).
I know that I can set ids dynamically, but I haven't had any luck passing functions to the "data-target" attribute.
<table class="table table-hover">
<thead class>
<tr>
<th style="width:5%"></th>
<th>Sample</th>
<th>Reference</th>
<th>Cost</th>
<th>Sum</th>
</tr>
</thead>
<tbody>
<div class="container" id="accordion">
<div class="card">
{% for r in result %}
<tr>
<td>
<button type="button" class="fa fa-chevron-right rotate" data-toggle="collapse"
data-target="#demo" onclick="">
</button>
</td>
<td> {{ r.split.0 }} </td> <!-- sample word -->
<td> {{ r.split.2 }}</td> <!-- ref word -->
<td> {{ r.split.4 }}</td> <!-- cost -->
<td> {{ r.split.3 }}</td> <!-- sum -->
</tr>
<tr>
<td id="demo" class="collapse" colspan="5" >
<!-- COLLAPSE CONTENT -->
</td>
</tr>
{% endfor %}
</div>
</div>
</tbody>
</table>
The "toogle button" have this HTML code:
<button type="button" class="fa fa-chevron-right rotate" data-toggle="collapse"
data-target="#demo">
and the collapsible content is the following:
<td id="demo" class="collapse">[...]</td>
It's normal every toggle button show or hide all collapsible contents in your page, because all these elements are related to the same #demo identifier.
You have to make sure the id of collapsible content is unique accross all the document, and ensure the corresponding button references the same unique id. Maybe use your result id (from context variable) to do something like that:
<button type="button" class="fa fa-chevron-right rotate" data-toggle="collapse"
data-target="#demo-{{ r.pk }}">
<td id="demo-{{ r.pk }}" class="collapse">[...]</td>
EDIT: Of course, you have to adapt it to YOUR data. In this example, I imagine your list result contain many model instances, so in each result r, the value r.pk is unique.
In your template, if results contain something else, you have to make sure a unique str or int is extracted from each value to uniquify the idyou write into your HTML.
Maybe it will be demo-{{ r.split.6 }} or demo-{{ r.a_unique_attr_in_my_object }} or demo-{{ r.slugify }}.
Try to put the content you want to hide under the " COLLAPSE CONTENT ".
like this:
<table class="table table-hover">
<thead class>
<tr>
<th style="width:5%"></th>
<th>Sample</th>
<th>Reference</th>
<th>Cost</th>
<th>Sum</th>
</tr>
</thead>
<tbody>
<div class="container" id="accordion">
<div class="card">
{% for r in result %}
<tr>
<td>
<button type="button" class="fa fa-chevron-right rotate" data-toggle="collapse"
data-target="#demo" onclick="">
</button>
</td>
</tr>
<tr>
<td id="demo" class="collapse" colspan="5" >
<td> {{ r.split.0 }} </td> <!-- sample word -->
<td> {{ r.split.2 }}</td> <!-- ref word -->
<td> {{ r.split.4 }}</td> <!-- cost -->
<td> {{ r.split.3 }}</td> <!-- sum -->
</td>
</tr>
{% endfor %}
</div>
</div>
</tbody>
</table>
By the way, don't forget the Bootstrap CDN

How to display 2 queryset list Frond end?(Django ListView get_queryset)

I got 2 queryset list expired_item and queryset in Django ListView, but I don't know when item is expired(queryset is empty), how to display another list expired_item on frond end, no matter what I changed in abc.html, expired_item won't dispaly, I pasted my code as below:
class ABCListView(ListView):
model = ABC
ordering = ('name', 'skill_course')
context_object_name = 'abcs'
template_name = ''
def get_queryset(self, **kwargs):
# Omitted
......
......
# Omitted
expired_item = list(ABC.objects.filter(pk__in=aa).exclude(pk__in=z))
queryset = Permit.objects.filter(pk__in=z)
return queryset
And my html file of abc.html as below:
{% extends 'base.html' %}
{% block content %}
<nav aria-label="breadcrumb">
</nav>
<h2 class="mb-3">My Items list</h2>
<div class="card">
<table class="table mb-0">
<thead>
<tr>
<th>Name</th>
<th>Department</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
{% for a in abcs %}
<tr>
<td class="align-middle">{{ a.name }}</td>
<td class="align-middle">{{ a.department.get_html_badge }}</td>
<td class="align-middle badge badge-pill badge-danger">{{ a.status }}</td>
</tr>
{% empty %}
{% endfor %}
</tbody>
</table>
</div>
<h2 class="mb-3">My Expired Items list</h2>
<div class="card">
<table class="table mb-0">
<thead>
<tr>
<th>Name</th>
<th>Department</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
{% for b in expired_item %}
<tr>
<td class="align-middle">{{ b.name }}</td>
<td class="align-middle">{{ b.department.get_html_badge }}</td>
<td class="align-middle badge badge-pill badge-danger">{{ a.status }}</td>
</tr>
{% empty %}
{% endfor %}
</tbody>
</table>
</div>
<div class="card-footer">
{% endblock %}
Thanks so much for any advice!
I would suggest use a normal django view. This Generic ListView is just created for the use of one list. Just pass both querysets in your context and render your template with that.
You could also use get_context_data() but this would be more or less hacky and not the qay I would recommend.

Toggle Checkbox in Django and Write to Database

I have some model
from django.db import models
class Model1(models.Model):
title = models.CharField(max_length=300)
boolean1 = models.BooleanField(default=False)
boolean2 = models.BooleanField(default=False)
and am currently displaying all database entries in a template via the following bootstrap table:
<div class = 'table-responsive'>
<table class='table table-striped'>
<thead>
<th>Title</th>
<th>Boolean 1</th>
<th>Boolean 2</th>
</thead>
{% if model1_list %}
{% for Model1 in model1_list %}
<tbody>
<tr>
<td>{{ Model1.title }}</td>
<td>{{ Model1.boolean1 }}</td>
<td>{{ Model1.boolean2 }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
I'd like to display the boolean values as checkboxes rather than text, and to be able to check and uncheck the values and have it be reflected in the database (i.e., if the database is checked, the value should be True).
What would be a way to implement this?
Just use IF's:
<div class = 'table-responsive'>
<table class='table table-striped'>
<thead>
<th>Title</th>
<th>Boolean 1</th>
<th>Boolean 2</th>
</thead>
{% if model1_list %}
{% for Model1 in model1_list %}
<tbody>
<tr>
<td>{{ Model1.title }}</td>
<td>
<div class="checkbox">
<label><input type="checkbox" {% if Model1.boolean1 %} checked {% endif %}>Boolean 1</label>
</div>
</td>
<td>
<div class="checkbox">
<label><input type="checkbox" {% if Model1.boolean2 %} checked {% endif %}>Boolean 2</label>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
When the user clicks, you want to send this information to the DB without refreshing the page? If yes, you need to do an ajax request to set this information to DB using JSON.Something like that:
$.ajaxFunction = function(){
var boolean1 = $("#boolean1").val(),
boolean2 = $("#boolean2").val(),
csrf_token = $("#csrf_token").val();
data_send = {
"boolean1": boolean1,
"boolean2": boolean2,
"csrfmiddlewaretoken": csrf_token
};
//jquery
$.ajax({
type: "post",
url: $("/url/ajax/").val(),
data: data_send,
success: function(data_receive){
if(data['boolean1']==true){
...
}
...
}
});
}
If no, you can just do a to POST this information and refresh the page!