0

Hi I would like to create table using JS datatables library.

I got problem when passing value in template to js script. I created JSON object from my table which I want to display. It's passed correctly to template, when I display it everything is fine, but when trying to pass it to script nothing happend and I got empty table.

Thats the way I do it:

class VotesList(generic.ListView):
    model = Vote
    template_name = 'votes-list.html'
    def get_context_data(self, **kwargs):
        votes = Vote.objects.all().values('user', 'group', 'council')
        votes_json = json.dumps(list(votes))
        context = super(VotesList, self).get_context_data(**kwargs)
        context['orderby'] = self.request.GET.get('orderby', 'created_date')
        context['json_data'] = votes_json

    return context

template:

{% block javascript %}
{% load static %}

<script type="text/javascript">
$(document).ready(function() {

    var json=JSON.parse('{{ json_data | safe }}');
    $('#votes_list').DataTable({
       data: json,
        columns:[
        { title: "user" },
        { title: "group" },
        { title: "council" }]
    } );
};

</script>

{% endblock %}

{% block content %}

    <p>{{ json_data | safe }}</p> <<< here data is printed fine
    {% if vote_list %}

        <table id="votes_list" class="display", style="width:100%">
            <thead>
                <tr>
                    <th>Właściciel</th> 
                    <th>Grupa</th> 
                    <th>Rada</th> 
                </tr>
            </thead>

        </table>

    {% else %}
        <p>Brak głosowań!</p>
    {% endif %}

{% endblock %}

and output data looks like that:

[{"user": 2, "group": 1, "council": 1}, {"user": 2, "group": 2, "council": 1}, {"user": 3, "group": 1, "council": 1}, {"user": 2, "group": 1, "council": 1}, {"user": 2, "group": 2, "council": 2}, {"user": 1, "group": 1, "council": 2}, {"user": 3, "group": 1, "council": 1}, {"user": 2, "group": 1, "council": 1}, {"user": 1, "group": 1, "council": 2}, {"user": 1, "group": 2, "council": 1}, {"user": 1, "group": 1, "council": 1}, {"user": 1, "group": 1, "council": 1}]

My second question is about something else: I'm storing lot of information as choices:

STATUS_INACTIVE = 0
STATUS_ACTIVE = 1
STATUS_FINISHED = 2
STATUS_CHOICES = (
    (STATUS_INACTIVE, 'Inactive'),
    (STATUS_ACTIVE, 'Active'),
    (STATUS_FINISHED, 'Finished'),
)

How to pass not numbers but this human readable values ('Inactive') to JSON above?

orzel
  • 15
  • 1
  • 7
  • For your second question you can try get_status_display. For your first question why are you converting to json? Why not just render the context as a table? – leelum1 Jul 18 '18 at 18:53
  • what do you mean as table? how then pass it to JS? – orzel Jul 18 '18 at 19:06

3 Answers3

1

For 1st question, try adding <tbody></tbody> after </thead> tag. Rerun the code.

For DataTables to be able to enhance an HTML table, the table must be valid, well formatted HTML, with a header (thead) and a single body (tbody).

There is another simpler way to render datatable.

views.py -

context['json_data'] = votes # no need to use json.dumps


In html-

   <table id="votes_list" class="display", style="width:100%">
        <thead>
            <tr>
                <th>Właściciel</th> 
                <th>Grupa</th> 
                <th>Rada</th> 
            </tr>
        </thead>
        <tbody>
            {% for data in json_data %}
                <tr>{{ data.user }}</tr>
                <tr>{{ data.group }} </tr>
                <tr>{{ data.council }} </tr>
            {% endfor %}
        </tbody>
   </table>

    <script type="text/javascript">
        $(document).ready(function() {
            $('#votes_list').DataTable();
        }
    </script>

For 2nd question -

{% if data.user == 1 %}
   Active
{% elif data.user == 2%}
   Inactive
{% else %}
   Finished
{% endif %}
OR 
{% if data.group == 1 %}
   {{ status_dict.0 }}
{% elif data.group == 2%}
   {{ status_dict.1 }}
{% else %}
   {{ status_dict.2 }}
{% endif %}

>>>status_dict = dict(STATUS_CHOICES)
{0: 'Inactive', 1: 'Active', 2: 'Finished'}

In datatable - you can apply the same logic. for example-

  "columns": [
    { "data": "engine" },
    { "data": "browser" },
    {
      "data": "platform",
      "render": function(data, type, row, meta) { 
                      if(true)
                          return “display this” 
                      };
                      return “false"
    }
  ]
Mohit Rustagi
  • 198
  • 1
  • 10
0

if you pass your data in your views like this

class VotesList(generic.ListView):
    model = Vote
    template_name = 'votes-list.html'

    def get_context_data(self, **kwargs):
        context = super(VotesList, self).get_context_data(**kwargs)
        context['votes'] = Vote.objects.all()
        return context

Then in your template you could have


{% block javascript %}
    {% load static %}
    
    <script type="text/javascript">
    $(document).ready(function() {
        $('#votes_list').DataTable({
           
        });
    });
    
    </script>
    
    {% endblock %}
    
    {% block content %}
    
        {% if vote_list %}
    
            <table id="votes_list" class="display", style="width:100%">
                <thead>
                  <th>Właściciel</th> 
                  <th>Grupa</th> 
                  <th>Rada</th> 
                </thead>
                <tbody>
                  {% for vote in votes %}
                    <tr>
                      <td>{{ vote.user }}</td>
                      <td>{{ vote.group}}</td>
                      <td>{{ vote.countcil }}</td>
                    <tr>
                  {% endfor %}
                </tbody>
            </table>
    
        {% else %}
            <p>Brak głosowań!</p>
        {% endif %}
    
    {% endblock %}

It should render as a JS Datatable

leelum1
  • 1,224
  • 10
  • 19
  • Hm yes you right, but I want to make table with "child-row" https://datatables.net/examples/api/row_details.html When I click on row It will display more information about object. Not all collumns are show at begining but only few and on click will be more information. So I stopped on passing this variable to json with this child-rows. So yours soulution will also should be fine here? – orzel Jul 18 '18 at 19:30
  • Yes this solution should work as well as passing it as json. I think this way is more straightforward though. When you are populating the child row you can insert the variables in the same way in the javascript; using `{{ vote.something }}` – leelum1 Jul 18 '18 at 19:41
0

For your first question, I would store your your template variable in a javascript variable like so var data = "{{ template_var }}" and then use that new variable where you are trying to use it now. Then you should be able to handle what you are trying to do.

Mind you other answers will tell you to just create a table, but I know you are using DataTables and in addition if you have over 50 objects you are trying to load in the table you may run into problems of loading speed. So, it may be good to do what you are doing and this will allow you to AJAX and retrieve the next set of data working with pagination. This is something that can be addressed for future proofing an application.

Oh Great One
  • 374
  • 2
  • 17
  • Yes I read about ajax but dont really know how to start with it – orzel Jul 18 '18 at 19:35
  • Hmm im passing to template using dump: json.dumps(list(votes)) and when I doing var data = "{{ json_data | safe }}" its still same – orzel Jul 18 '18 at 19:38
  • So, ajax in django is pretty easy, there are tutorials all over. In regards to other comment the problem probably lies from it being recognized as a string and is not being parsed correctly from your JSON.parse. Try console logging the new js variable and respond here with it. On a side note maybe what you should do is just render the template with no data and then when the page is ready, do an AJAX call and return a JsonResponse object which is apart of Django. Then you can easily place the data in the table from Javascript. This will mitigate slow loading problems with lots of data. – Oh Great One Jul 18 '18 at 20:25