1

I am trying to get the columns required for a table from a Model. It works fine. But when I change the Model data from where the columns are taken, server needs to be restarted for it to take effect.

tables.py:

class InventoryTable(tables.Table):
    ip_addr = tables.Column(linkify=("detailed_view", (tables.A("ip_addr"), )))

    class Meta:
        a = Inventory_views.objects.get(view_name="default")
        activeList = []

        for field in a._meta.fields:
            if field.name != "default" and (getattr(a, field.name) == True):
                activeList.append(field.name)

        activeTuple = tuple(activeList)
        model = Inventory_basic
        template_name = 'django_tables2/bootstrap.html'
        fields = (activeTuple)

views.py:

def inventory_v2(request):
    if 'search_query' in request.GET:
        form = searchForm(request.GET)
        if form.is_valid():
            search_query = form.cleaned_data.get('search_query')
            table = InventoryTable(Inventory_basic.objects.filter(ip_addr__icontains=search_query))
            RequestConfig(request).configure(table)
            return render(request, 'jd_inventory_v2.html', {'table': table, 'form': form})
    else:
        form = searchForm()
    table = InventoryTable(Inventory_basic.objects.filter(ip_addr__icontains="NULL"))
    RequestConfig(request).configure(table)
    return render(request, 'inventory_v2.html', {'table': table, 'form': form})

models.py:

class Inventory_views(models.Model):
    view_name = models.CharField(max_length=25,default="NA", verbose_name='View Name')
    hw_serialno = models.BooleanField(default=True, verbose_name='Hardware SN')
    location = models.BooleanField(default=True, verbose_name='Location')
    ip_addr = models.BooleanField(default=True, verbose_name='IP Address')

UPDATE:

I was able to find another way to do this using metaclass from this example : https://stackoverflow.com/a/703888/1998915

New Code: tables.py:

class InventoryTable(tables.Table):
    def __init__(self, *args, **kwargs):
        exclude_list=kwargs.pop('exclude_list', '')
        super(InventoryTable, self).__init__(*args, **kwargs)

        for field in exclude_list:
            del self.fields[field]

        class Meta:
            model = Inventory_basic

views.py:


def jd_inventory_v2(request):

    if 'search_query' in request.GET:
        form = searchForm(request.GET)
        if form.is_valid():
            search_query = form.cleaned_data.get('search_query')
            table = InventoryTable(Inventory_basic.objects.filter(ip_addr__icontains=search_query),exclude_list=inactiveFields)
            RequestConfig(request).configure(table)
            return render(request, 'jd_inventory_v2.html', {'table': table, 'form': form})

    else:
        form = searchForm()
    inactiveFields = viewFilter()
    table = InventoryTable(data=Inventory_basic.objects.filter(ip_addr__icontains="NULL"), exclude_list=inactiveFields)
    RequestConfig(request).configure(table)
    return render(request, 'jd_inventory_v2.html', {'table': table, 'form': form})

But now getting the error : 'InventoryTable' object has no attribute 'fields'

Amar C
  • 374
  • 5
  • 17
  • I don't understand what the problem is. Could you describe it more clearly? – Ralf Jul 11 '19 at 20:37
  • sure. So I have table "InventoryTable" from model "Inventory_basic". So the table contains many variables and i don't want all of them to be displayed all the time. So instead they take value from another model. This works the first time a start the server. When I change the "column model" data, refreshing the webpage doesn't make django redraw the table. Only restart redraws the table. – Amar C Jul 11 '19 at 20:41

2 Answers2

2

I don't think the approach you used will work.

You have procedural code inside class Meta: instead of the standard of just defining class attributes. Python classes only get read into memory once, at server start in this case, not every time a request is processed. So the code you have inside class Meta: only is run at server start.

You need to find a different approach for this. Have you look in the docs for a dynamic definition of columns?

This similar question seems to use an argument extra_columns in the table constructor.

Ralf
  • 16,086
  • 4
  • 44
  • 68
  • Oh. that makes sense. But I cant find any other way to define "fields" other than inside the Meta class. Is there any other way to achieve this? Thanks – Amar C Jul 11 '19 at 20:51
  • @AmarC updated my answer with link to a related question. – Ralf Jul 11 '19 at 21:00
  • That example was not really what i was looking for, but i did find another approach for this. Could you please check the update. – Amar C Jul 11 '19 at 22:19
1

Was finally able to achieve what I wanted. I went back to my original approach and rather than adding new column, I excluded the ones i didn't need. It was very simple. https://stackoverflow.com/a/20033827/1998915

Amar C
  • 374
  • 5
  • 17