Static Model variable that determines which model fields are displayed in ListView

I am trying to make a generic ListView view that can be populated by the model connected to it. Therefore I have inserted several static variables in my model that are used to populate the view. These are to the bottom of the model definition.

class AssignmentAd(models.Model):
    class StatChoices(models.TextChoices):
        REGISTERED = "Registered"
        PENDING = "Pending"
        CANCELED = "Canceled"

    class FieldChoices(models.TextChoices):
        JFS = "JFS"
        JAVA = "Java"
        CLOUD = "Cloud"

    # id = models.CharField(max_length=20)
    # contact_person = models.ForeignKey(Question, on_delete=models.CASCADE)
    status = models.CharField(max_length=20, choices=StatChoices.choices, default=StatChoices.PENDING)
    # period = models.DateTimeField('period')
    # broker
    deadline = models.DateField('Deadline')
    field = models.CharField(max_length=20, choices=FieldChoices.choices, default=FieldChoices.JFS)
    location = models.CharField(max_length=40)
    remote = models.IntegerField(
        default=0,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(0)
        ]
     )
    # status_reason
    # url
    title = models.CharField(max_length=200)

    REQUIRED_FIELDS = ['status', 'period', 'title']

    # These static values are used to populate the ListView template
    LIST_HEADLINE = 'assignment ads'

    SINGLE_ITEM = 'assignment ad'

    LIST_COLTITLES = ['title', 'field', 'status', 'deadline', 'remote', 'location']

    LIST_COLDATA = [title, field, status, deadline, remote, location]

I am having my list column headlines populated by reading the LIST_COLTITLES field but I am unable to read the column data for each object. Here is my template and how I tried to do it by reading the LIST_COLDATA.

In the view I am importing everything into the context like so:

class TrackAssignmentAds(generic.ListView):
    model = AssignmentAd
    template_name = 'track/assignment_ads.html'
    context_object_name = 'model_objs'
    paginate_by = 5

    def get_context_data(self, **kwargs):
        context = super(TrackAssignmentAds, self).get_context_data(**kwargs)
        context['currentpage'] = 'assignment_ads'
        context['listheadline'] = TrackAssignmentAds.model.LIST_HEADLINE
        context['listsingleitem'] = TrackAssignmentAds.model.SINGLE_ITEM
        context['listcoltitles'] = TrackAssignmentAds.model.LIST_COLTITLES
        context['listcoldata'] = TrackAssignmentAds.model.LIST_COLDATA
        context['model_form'] = AssignmentAdForm()
        return context

    def post(self, request, *args, **kwargs):
        form = AssignmentAdForm(request.POST)
        if form.is_valid():
            form.save()
        else:
            messages.success(request, "Invalid form")
        return redirect('assignment_ads')

Then I am using these values from context in the template.

<div class="relative md:pt-20 pt-12 h-full">
        <div class="flex flex-wrap">
            <div class="w-full mb-12 px-4">
                <div class="relative flex flex-col min-w-0 break-words w-full mb-6 shadow-lg rounded bg-white">
                    <div class="rounded-t mb-0 px-4 py-3 border-0">
                        <div class="flex flex-wrap items-center">
                            <div class="relative px-4 flex-grow flex-1">
                                <h3 class="font-semibold text-lg text-blueGray-700">
                                    {{ listheadline|title }}
                                </h3>
                            </div>
                            <div class="relative px-4">
                                <button
                                        class="bg-teal-500 text-white active:bg-teal-600 font-bold uppercase text-xs px-4 py-2 rounded shadow hover:shadow-md outline-none focus:outline-none mr-1 ease-linear transition-all duration-150"
                                        type="button" onclick="openPopUpForm();">
                                    Add New
                                </button>
                            </div>
                        </div>
                    </div>
                    <div class="block w-full overflow-x-auto">
                        <!-- Projects table -->

                        <table class="items-center w-full bg-transparent border-collapse table-fixed">
                            <thead>
                            <tr>
                                {% for coltitle in listcoltitles %}
                                    <th class="px-6 align-middle border border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                                        {{ coltitle|upper }}
                                    </th>
                                {% endfor %}
                                <th class="px-6 align-middle border border-solid py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left bg-blueGray-50 text-blueGray-500 border-blueGray-100">
                                </th>
                            </tr>
                            </thead>
                            <tbody>
                            {% for ad in model_objs %}
                            {% for data in listcoldata %}
                                <td class="border-t-0 px-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap p-4">
                                    {{ ad.data }}
                                </td>
                                {% endfor %}
                                <td
                                        class="border-t-0 px-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap p-4 text-right">
                                    <a class="text-blueGray-500 block py-1 px-3" href="#pablo"
                                       onclick="openDropdown(event,'table-light-1-dropdown')">
                                        <i class="fas fa-ellipsis-v"></i>
                                    </a>
                                    <div class="hidden bg-white text-base z-50 float-left py-2 list-none text-left rounded shadow-lg min-w-48"
                                         id="table-light-1-dropdown">
                                        <a class="text-sm py-2 px-4 font-normal block w-full whitespace-nowrap bg-transparent text-blueGray-700"
                                           href="#pablo">Action</a><a
                                            class="text-sm py-2 px-4 font-normal block w-full whitespace-nowrap bg-transparent text-blueGray-700"
                                            href="#pablo">Another
                                        action</a><a
                                            class="text-sm py-2 px-4 font-normal block w-full whitespace-nowrap bg-transparent text-blueGray-700"
                                            href="#pablo">Something
                                        else here</a>
                                        <div class="h-0 my-2 border border-solid border-blueGray-100">
                                        </div>
                                        <a class="text-sm py-2 px-4 font-normal block w-full whitespace-nowrap bg-transparent text-blueGray-700"
                                           href="#pablo">Seprated
                                            link</a>
                                    </div>
                                </td>
                            </tr>
                            <!--                                {{ ad.title }} - {{ ad.field }} - {{ ad.status }} - {{ ad.deadline }} - {{ ad.remote }} - {{ ad.location }}<br>-->
                            {% endfor %}

                            </tbody>
                        </table>
                    </div>
                    <hr class="mt-4 md:min-w-full"/>
                    <div class="rounded-t mb-0 px-4 py-3 border-0">
                        <div class="flex flex-wrap justify-end">
                            <div class="px-4 font-bold">
                                <a class="hover:text-emerald-500" href="
                                {% if page_obj.has_previous %}
                                    ?page={{ page_obj.previous_page_number }}
                                {% endif %}
                                "><i
                                        class="fas fa-angle-left"></i></a>
                                <span>{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
                                <a class="hover:text-emerald-500" href="
                                {% if page_obj.has_next %}
                                    ?page={{ page_obj.next_page_number }}
                                {% endif %}
                                "><i
                                        class="fas fa-angle-right"></i></a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        {% include 'track/snippets/footer.html' %}
</div>

Sorry for the chaos of above HTML. The bit that wont work is:

{% for ad in model_objs %}
  {% for data in listcoldata %}
    <td class="border-t-0 px-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap p-4">
      {{ ad.data }}
    </td>
  {% endfor %}
{% endfor %}

I need to extract the fields of the model objects that are defined in the LIST_COLDATA static variable and insert them above where {{ ad.data }} iteratively.

I had to make a custom tag https://docs.djangoproject.com/en/4.1/howto/custom-template-tags/

Like so:

from django import template


def getattribute(value, arg):
    """Returns a model object's field value based on string name arg"""
    if hasattr(value, str(arg)):
        return getattr(value, arg)


register = template.Library()
register.filter('getattribute', getattribute)

And then use it in the HTML template like so:

{% for ad in model_objs %}
{% for data in ad.LIST_COLDATA %}
{{ ad|getattribute:data }}
{% endfor %}
{% endfor %}

Where data is a LIST_COLDATA is a list of strings that indicates which fields should populate the list columns. The custom tag helps extract the specific field by reading the strings from the list.

Back to Top