André Guerra
André Guerra

Reputation: 506

How to fix 'Argument data to tableXXX is required' in django-tables2?

I'm setting up a webstore manager and I'm relying on django-tables2 package to show a list of products using the SimpleTableMixin. I want to add the filter/search capability to the view. As recommended by the django-tables2 package one can rely on django-filter package to provide filtering. However, it the case of a model with many fields it becomes almost impossible to query and develop forms for those efficiently. My goal is to use django-haystack to have a single input search form as a mean to query the model instances which should be displayed in a similar table/form.

I've tried to add the SimpleTableMixin to the django-haystack package generic SearchView. However I keep on getting the following error:

TypeError at /manager/front/products/
Argument data to ProductTable is required

So far my implementation goes as follow:

view:

# ############## Products ############## (previous implementation with django-filter)
# @method_decorator(staff_member_required, name='dispatch')
# class ProductList(SingleTableMixin, FilterView):
#     model = Product
#     table_class = tables.ProductTable
#     filterset_class = filters.ProductFilter
#     template_name = 'manager/front/products/product_list.html'

############## Products ##############
@method_decorator(staff_member_required, name='dispatch')
class ProductList(SingleTableMixin, SearchView):
    model = Product
    table_class = tables.ProductTable
    template_name = 'manager/front/products/product_list.html'

tables:

import django_tables2 as tables
from front.models import Product

class ProductTable(tables.Table):
    class Meta:
        model = Product
        template_name = 'django_tables2/bootstrap.html'

search_indexes.py:

from haystack import indexes
from front.models import Product

class ProductIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        return Product

urls:

path('front/products',views.ProductList.as_view(),name="manage_products"),    

template:

{% extends 'base_site.html' %}
{% load render_table from django_tables2 %}
{% block content_title %}Manage Products{% endblock%}
{% block content %}
<form action="" method="get" class="form form-inline">
    {{ form }}
    <button class="btn btn-default" type="submit">Search</button>
</form>
{% render_table table %}
{% endblock %}

How can I remove that error and provide efficient search abilities to my list views?

Upvotes: 0

Views: 1047

Answers (1)

Serafeim
Serafeim

Reputation: 15084

Are you sure that you are using haystack.generic_views.SearchView and not haystack.views.SearchView? Please notice that on https://django-haystack.readthedocs.io/en/latest/views_and_forms.html it says:

As of version 2.4 the views in haystack.views.SearchView are deprecated in favor of the new generic views in haystack.generic_views.SearchView which use the standard Django class-based views which are available in every version of Django which is supported by Haystack.

Thus if you're using haystack.views.SearchView then the get_context_data of SingleTableMixin will never be called thus no table will be put in your context (i.e table will be empty). Actually because I dislike the behavior of {% render_table %} when its parameter is empty (it behaves different than the other Django tags/filters i.e it throws an exception while the django ones silently ignore that) I usually put it inside some {% if table %} checks.

UPDATE

It seems that for whatever reason the data is not passed to the table. I am not sure why, I can't test it right now but from a quick look at the source code your implementation should have been working (considering that SearchView has a get_queryset and TableMixin uses the get_queryset to retrieve its data). In any case you try overriding some methods of TableMixin to make sure that the table is properly returned (take a look at TableMixin here: https://django-tables2.readthedocs.io/en/latest/_modules/django_tables2/views.html).

I think the most definite solution would be to just bite the bullet and override get_table yourself. So, try adding something like this to your class:

def get_table(self, **kwargs):
    table_class = self.get_table_class()
    # I only change this line from the original to make sure that the self.get_queryset() is called to return the data
    table = table_class(data=self.get_queryset(), **kwargs)
    return RequestConfig(self.request, paginate=self.get_table_pagination(table)).configure(
        table
    )

One idea that just popped in my mind. Is there a possibility that the get_queryset() method of SearchView returns None due to bad configuration or whatever?

Upvotes: 1

Related Questions