1

enter image description here

I am trying to hyperlink the rows of the class column of to serve as link to other pages. I read the doc about hyperlinks as well as some posts here such as The linkcolumn about django-tables2. but they don't resolve my problem because from my understanding the link is made by referencing the Pks of a UNIQUE TABLE in each row.

In my situation, the link is made using a different model for each row so I don't know how to reference a pk.

Here is what I have been able to do so far: MAIN PAGE TABLE:

class ClassificationTable(tables.Table):
    
    Class = tables.TemplateColumn('<a href="{{record.extra_details_view}}">{{record.Class}}</a>')
    revenue_proportion = tables.Column(gettext_lazy("revenue proportion"),localize= True)
    Quantity_of_items = tables.Column(gettext_lazy("quantity of items"),localize= True)

    class Meta:
        model = Classification
        fields = ('Class',
                  'revenue_proportion',
                  'Quantity_of_items',
                  
                 )
        template_name = "django_tables2/bootstrap4.html"
 

here is the html code for the main page:

{%  load static %}
{% load i18n %}
{% load django_tables2 %}
class="no-padding-bottom">
          <div class="container-fluid">
            <div class="row">
              <div class="col-lg-8">

                {% render_table table %}
              </div>

here is the model for classification:

class Classification(models.Model):
    Class = models.CharField(max_length=10, primary_key=True)
    revenue_proportion = models.FloatField(default=0)
    Quantity_of_items = models.IntegerField(default=0)
    
    def __str__(self):
       return self.Class

Here are the models used in the other pages:

class class_aa1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Id

    def extra_details_view(self):
        return reverse("exostocksaas.dashboard.classAA1page")
    

class class_a1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Référence

    def extra_details_view(self):
        return reverse("exostocksaas.dashboard.classA1page")
    
    
class class_b1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Référence

    def extra_details_view(self):
        return reverse("exostocksaas.dashboard.classB1page")
    
    
class class_c1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Référence

    def extra_details_view(self):
        return reverse("exostocksaas.dashboard.classC1page")
    
    
class class_d1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Référence

    def extra_details_view(self):
        return reverse("exostocksaas.dashboard.classD1page")
    

I am hoping that someone could help me deblock this issue, I am banging my head on it for too long. I would be happy to provide more info if necessary. Cheers

UPDATE: I tryed as suggested in the answer (updated my code), now the rows in the class column are clickable as links but they seem to be calling the same page as nothing change.

here is what I get in the logs:

Traceback (most recent call last):
  File "/home/ubuntu/exo/lib/python3.6/site-packages/django/template/base.py", line 849, in _resolve_lookup
    (bit, current))  # missing attribute
django.template.base.VariableDoesNotExist: Failed lookup for key [extra_details_view] in <Classification: ClassAA>
DEBUG Exception while resolving variable 'extra_details_view' in template 'dashboard/analytics.html'.
Traceback (most recent call last):
  File "/home/ubuntu/exo/lib/python3.6/site-packages/django/template/base.py", line 828, in _resolve_lookup
    current = current[bit]
TypeError: 'Classification' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ubuntu/exo/lib/python3.6/site-packages/django/template/base.py", line 836, in _resolve_lookup
    current = getattr(current, bit)
AttributeError: 'Classification' object has no attribute 'extra_details_view'

I am not familiar with the suggested technique to reference links, so I am not sure what is happening, someone has a clue?

Murcielago
  • 905
  • 1
  • 8
  • 30

1 Answers1

1

I found this question that tells you how to create arbitrary links for a column: django-tables2 linkColumn external url

instead of this:

Class = tables.Column(gettext_lazy("class"),localize= True)

try this:

Class = tables.TemplateColumn('<a href="{{record.extra_details_view}}">{{record.class}}</a>')

Then you will need to define a callable on each of your model classes for the method extra_details_view to return the URL for that view:

class class_aa1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Id

    def extra_details_view(self):
        return reverse("myproj.myapp.myview")
        // or hardcode it
        return "/this/class/extra/details/view/url"

Edit

Maybe try this instead and see if you can get the links to show up at all?

Class = tables.TemplateColumn('<a href="{{record.extra_details_view}}">Class Name Goes Here</a>')

Edit 2

Maybe back to this to see if an attribute can get picked up rather than a method:

Class = tables.TemplateColumn('<a href="{{record.extra_details_url}}">{{ record.Class }}</a>')

and

class class_aa1(models.Model):
    Id = models.CharField(max_length=100, primary_key=True, verbose_name= 'items')
    revenue_contribution_in_percentage = models.FloatField(default=0, verbose_name= 'value contribution')
    margin = models.FloatField(default=0, verbose_name= 'value')
    number_of_orders_placed = models.FloatField(default=0, verbose_name= 'number of orders placed')
    number_of_sales = models.FloatField(default=0, verbose_name= 'number of sales')
    
    def __str(self):
        return self.Id

    extra_details_url = reverse("myproj.myapp.myview")
    # or hardcode it
    extra_details_url = "/this/class/extra/details/view/url"

If the django tables2 project isn't recognizing the class' method perhaps it'll read just a normal variable.

Edit 3

I think we've figured it out! The way you've setup your database models I don't think that there's a good way to achieve a direct linkage between the individual Classification and the individual model's class. You're mapping that manually already so I think you can map the URL manually too.

class Classification(models.Model):
    Class = models.CharField(max_length=10, primary_key=True)
    revenue_proportion = models.FloatField(default=0)
    Quantity_of_items = models.IntegerField(default=0)
    extra_details_url = models.URLField()
    
    def __str__(self):
       return self.Class

You'd have to put the entire URL in there including the http://.... which isn't ideal but it would work.

I think a better option would be something like this:

class Classification(models.Model):
    Class = models.CharField(max_length=10, primary_key=True)
    revenue_proportion = models.FloatField(default=0)
    Quantity_of_items = models.IntegerField(default=0)
    extra_details_view = models.CharField()
    
    def __str__(self):
       return self.Class

    def extra_details_url(self):
        return reverse(self.extra_details_view)

In either case you'll need to change the template to:

Class = tables.TemplateColumn('<a href="{{record.extra_details_url}}">{{record.class}}</a>')

It's a little bit silly to make yet another name change like this but I'm suggesting it because it makes sense to name it what it is which is a URL. It also lets you free up the extra_details_view name to hold the value of the view itself like "exostocksaas.dashboard.classAA1page"

I think this will all work finally. Good luck!

Mike Sandford
  • 1,315
  • 10
  • 22
  • i followed your changes, while i don't get any error, the values in the class columns are not showing up, each row is empty in this column – Murcielago Aug 13 '20 at 20:45
  • What happens when you view the source? Are the links there but the text is missing? Maybe try instead of `{{ record.class }}` for the link name hard-code the string "Class name" and see if you can see something then. If that makes clickable links then the problem is coming up with the class name / link text. If that doesn't do anything then it seems like there are bigger problems. – Mike Sandford Aug 13 '20 at 22:22
  • i updated my post, take a look, the links are there but seem to pointing toward the original page – Murcielago Aug 14 '20 at 07:42
  • thank you for your update, unfortunately, I am stuck with the same output and the result, even trying to pass the url as a variable instead of a fonction – Murcielago Aug 14 '20 at 13:26
  • Oh! I think I figured it out. You need to figure out how to plumb the data between the individual models classes and the `Classification` model class. What is a `Classification`? Where is the code for that? That's the missing piece. – Mike Sandford Aug 14 '20 at 13:34
  • i just added the classification model. that's the thing that is blocking, very is no data link between Classification model and the sub classes models – Murcielago Aug 14 '20 at 13:40
  • 1
    THAT WORKS THANK YOU MiKE! If anyone stumbles here, what is needed is to put the link to the page inside of the db row "extra_details_view" – Murcielago Aug 14 '20 at 19:30
  • Great! Glad to hear it. – Mike Sandford Aug 14 '20 at 21:27