0

Part 1

I had my datatable working with obj iteration but I am moving to DRF-datatables.. and although I got the example site running no problem the actual implementation on my end is kicking my butt. Basically, I got my whole weekend to show a table that seems to be loading data (as pagination is showing the proper info) but my rows are all blank: https://i.stack.imgur.com/19LPp.png

Then I tried to add the "columns" section in the scripts and that breaks the whole table: https://i.stack.imgur.com/1Ln4A.png

If I change the ajax call to

"ajax": "/api/entry/?format=datatables",

then I get the most closely working table: https://i.stack.imgur.com/KvAtK.png - however the problem remains that the rows are empty and if I add the cols then everything breaks.

Where am I going wrong? I'm also not getting any error messages so it's hard to debug datatables.

Maybe Part 2..

Do I even need to go for DRF-datatables? My end goal is to be able to select multiple rows and then edit the trade for all those entries.

Example of the end goal

  1. Select 3 trade
  2. Click dropdown somewhere at the top of the table
  3. Select Trade PK from that dropdown
  4. Click Save
  5. Table shows the latest data

entry_list.html

{% extends "dashboard/base.html" %}
{% load i18n %}
{% block content %}

<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
    <h2 class="text-gray-800">{% block title %}{% trans "Imported Entries" %}{% endblock %}</h2>
    <a role="button" class="btn btn-success" href="{% url 'import' %}"><i
            class="fas fa-plus-circle"></i> Import New Entires</a>
</div>


<!-- Content Row -->
<div class="row">
    <div class="col-md-12">
        <table id="entrytable"
               class="table-hover table display"
               align="center"
               style="width:100%">
            <thead>
            <tr role="row">
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">ID
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Date
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Trade
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Type
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Symbol
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Amount
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Price
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Fee
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Reg Fee
                </th>
                <th class="sorting" tabindex="0" aria-controls="dataTable" rowspan="1"
                    colspan="1" aria-label="" style="">Ref
                </th>
            </tr>
            </thead>

        </table>
    </div>
</div>

{% endblock %}


{% block js %}

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/dataTables.bootstrap4.min.css"/>
<!--https://datatables.net/examples/server_side/select_rows.html-->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css"/>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.22/js/dataTables.bootstrap4.min.js"></script>


<script>

$(document).ready(function() {
    var selected = [];

    $("#entrytable").DataTable({
        "order": [[ 1, "desc" ]],
        "processing": true,
        "serverSide": true,
        "ajax": {
            "url": "/api/entry/?format=datatables",
            "type": "POST",
            "beforeSend": function(xhr) {
                xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token|escapejs }}");
            }
        },
        "columns": [
            {"data": "pk"},
            {"data": "date"},
            {"data": "trade.id"},
            {"data": "entry_type"},
            {"data": "symbol"},
            {"data": "amount"},
            {"data": "price"},
            {"data": "fee"},
            {"data": "reg_fee"},
            {"data": "transaction_id"},
        ]
        "rowCallback": function( row, data ) {
            if ( $.inArray(data.DT_RowId, selected) !== -1 ) {
                $(row).addClass('selected');
            }
        }
    });

    $('#entrytable tbody').on('click', 'tr', function () {
        var id = this.id;
        var index = $.inArray(id, selected);

        if ( index === -1 ) {
            selected.push( id );
        } else {
            selected.splice( index, 1 );
        }

        $(this).toggleClass('selected');
    } );
} );


</script>

{% endblock %}

Serializers.py

class EntrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Entry
        fields = '__all__'

Views.py

class EntryViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Entry.objects.all()
    serializer_class = EntrySerializer
    permission_classes = [permissions.IsAdminUser]
    filter_backends = (DjangoFilterBackend, OrderingFilter,)

models.py

class Entry(models.Model):
    ENTRY = 'entry'
    EXIT = 'exit'
    ENTRY_TYPE_CHOICES = [
        (ENTRY, 'Entry'),
        (EXIT, 'Exit'),
        # (DIVIDEND_RECEIVED, 'Dividend Received'),
        # (DIVIDEND_SOLD, 'Dividend Sold'),
    ]

    class Meta:
        verbose_name = "Entry"
        verbose_name_plural = "Entries"

    trade = models.ForeignKey(Trade, on_delete=models.CASCADE, null=True, blank=True)
    date = models.DateTimeField(null=True, blank=True, default=datetime.datetime.now)
    amount = models.FloatField(null=True)
    price = models.FloatField(null=True)
    fee = models.FloatField(null=True, blank=True)
    entry_type = models.CharField(max_length=5, choices=ENTRY_TYPE_CHOICES, default=ENTRY)
    reg_fee = models.FloatField(null=True, blank=True)
    transaction_id = models.CharField(max_length=100, null=True, blank=True)
    symbol = models.ForeignKey(Symbol, on_delete=models.SET_NULL, blank=True, null=True)
    created_by = models.ForeignKey(User, null=True, blank=True, editable=False, on_delete=models.CASCADE)
Alex Winkler
  • 469
  • 4
  • 25

1 Answers1

1

Do I even need to go for DRF-datatables?

You only need DRF Datatables if you are using server-side processing (as you are at present). You probably don't need server side processing unless you need to support large datasets (1000s of rows).

If your result set size is in the 100s, then stick with template rendering.

My end goal is to be able to select multiple rows and then edit the trade for all those entries.

It's definitely possible to do this with Datatables and JQuery. The datatables-select plugin will help. But it is tricky (as you have found). Try to read and understand the docs and examples before you start coding - this will definitely save you time in the long run.

UPDATE

If it's not working...

  1. Try to call the API URL on its own. Does it return the correct data?

  2. Make sure that column names match the names coming back from the API call. It can be tricky - make sure you are clear on how your API response is structured, and that you have declared columns correctly.

  3. Maybe start with a single simple column and get that working first. Then add in new columns.

  4. Set breakpoints in drf datatables - step through and see if anything is failing or wrong.

  5. Download and run the DRF DataTables example app - having a working implementation might help you isolate what is going wrong.

It definitely will work (I have used datatables with Django / DRF Datatables) - but it can be tricky to set up at first.

Matthew Hegarty
  • 3,791
  • 2
  • 27
  • 42
  • I'll be dealing with 1000's and quickly 10,000's of rows. Thanks for pointing that out. So it seems like the right path to go down. I think I've read every documentation page twice. I'm not totally sure where the error is coming from so atm I'm trying to find more example projects. The 3rd Imgur link shows that I can select rows already but no data is being populated. I find that super odd – Alex Winkler Nov 10 '20 at 06:31
  • Waaa thanks Matthew for sticking with me on this one. I felt like a lost puppy. The first step was the one that worked (although I did all the steps above at one point). I felt like there had to be a col off so I ran DRF and used http://127.0.0.1:8000/api/entry/ and made sure all lined up with the columns and . Phew.. time to get back to the original issue https://stackoverflow.com/questions/64623613/django-edit-or-delete-selected-rows-in-a-table-listview lol (maybe I'll see ya there again) – Alex Winkler Nov 10 '20 at 18:16