Search code examples
pythondjangojoindjango-tables2

Django-tables2: Populate table with data from different database tables (with model.inheritance)


I want to show data from different database tables on a django-tables2 table.

I have several apps with each app having some database tables (with each table in its own file). Project structure:

    --project
     -all
     -overview

all/models/compound.py

    class Compound (models.Model):
        name = models.CharField(max_length = 100, unique = True, verbose_name="Probe")
        dateAdded = models.DateField();

        class Meta:
            app_label = 'all'

all/models/probe.py

    class Probe(Compound):
       mechanismOfAction = models.CharField(max_length = 255, verbose_name="Mode of action")
       

      def get_absolute_url(self):
           return reverse('overview:probe_detail', args=[str(self.id)]) 

      def __str__(self):
           return f'{self.name}, {self.mechanismOfAction}'

      class Meta:
         app_label = 'all'

all/models/negativeControl.py

    class NegativeControl(Compound):
         probeId = models.ForeignKey(Probe, on_delete=models.CASCADE, related_name="controls", verbose_name="Control")

         class Meta:
              app_label = 'all'

overview/models/usageData.py

    class UsageData (models.Model):
         cellularUsageConc = models.CharField (max_length = 50, null = True, verbose_name="Recommended concentration")
    
          probeId = models.ForeignKey(Probe, on_delete=models.CASCADE, related_name="usageData")

          def __str__(self):
               return f'{self.cellularUsageConc}, {self.inVivoUsage}, {self.recommendation}'

          class Meta:
              app_label = 'overview'

all/tables.py

    class AllProbesTable(tables.Table):
          Probe = tables.Column(accessor="probe.name", linkify=True)  
          control = tables.Column(accessor="probe.controls")     
          mechanismOfAction = tables.Column()
          cellularUsageConc = tables.Column(accessor="usageData.cellularUsageConc")

          class Meta:
               template_name = "django_tables2/bootstrap5-responsive.html"

all/views.py

    class AllProbesView(SingleTableView):
          table_class = AllProbesTable
          queryset = queryset = Probe.objects.all().prefetch_related('usageData', 'controls')  
          template_name = "all/probe_list.html"

all/templates/all/probe_list.html

    {% load render_table from django_tables2 %}
    {% render_table table %}

The rendered table shows all headers correct and has data for the "Probe" and "Mode of action". For the "Control", I get "all.NegativeControl.None" and for the "Recommended concentration" "-". Why do I get "-" for the "Recommended concentration".

For a probe there can be more than one control. I would need to create a string from all control names such as control1, control2 to show it in the table. How can I do this?

This post was helpful but in my case it did not work.

I use Django 5.0.1 and Python 3.12.1.


Solution

  • You're very close. In the Table class, you simply use the related_name to access, then custom render to display:

    class AllProbesTable(tables.Table):
          control = tables.Column(accessor="controls") 
          cellularUsageConc = tables.Column(accessor="usagedata")
          # [...]
    
        def render_control(self, record):
            return [c.name for c in record.controls.all()]
    
        def render_cellularUsageConc(self, record):
            return [ud.cellularUsageConc for ud in record.usagedata.all()]