E
E
Eugene2016-01-24 13:51:27
Django
Eugene, 2016-01-24 13:51:27

Is it possible to use an indirect access to the context variable in the template?

The essence of the task - it is necessary to display a table with the totals by category. For example:
bacbdb533b9846039c095e87d6577d2e.jpg
Each user selects their categories. For each category, you can add several features. At the intersection of the user and category, the number of features is displayed.
To build a table, I use an SQL query and create a context variable.

sql = 'select pu.id, pu.user_id, '
for section in project.sections.all():
    sql += '  (select COUNT(*) from section ...
    sql += '   where pus.section_id = ' str(section.id)
    sql += '       and pus.id = pusp.profile_user_section_id ) count_in_section_' + str(section.id) + ','
sql += ' u.first_name, u.last_name '
sql += ' from ...'
sql += ' where ... '
users_list = list(project.profile_users.raw(sql, params=[project_id]))
context = {'project': project,
               'users_list': users_list,
               }
return render(request, template, context)

Thus columns with totals are created.
I have a question how to refer to the corresponding category column in the template by its name stored in the context variable, for example: column_name_1 ='item.count_in_section_' + str(section.id)
...
{% for item in users_list %}
                <tr>
                <td>{{ item.id }}</td>
                <td>{{ item.first_name }}</td>
                <td>{{ item.last_name }}</td>
                   {% for section in project.sections.all %}
                       <td>
                      <b> {{ column_name_1 }}</b>  <!-- ??? Нужна косвенная адресация -->
                       </td>
                   {% endfor %}
                </tr>
{% endfor %}
...

Perhaps this approach has no solution, but I hope there is a way to get the result. If you have any ideas please share with them. I found one solution, without "indirect addressing", but I don't like it.
I supplement the question with models. models.py file:
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

# Create your models here.


class Section(models.Model):
    name = models.CharField(max_length=25, verbose_name=_('Категория'))


class Criterion(models.Model):
    name = models.CharField(max_length=250, verbose_name=_('Критерий'))


class ProfileUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name=_('Пользователь'), unique=True)
    user_info = models.CharField(max_length=100)


class Project(models.Model):
    profile_users = models.ManyToManyField(ProfileUser, verbose_name=_('Участники'), through='ProjectProfileUser')


class ProjectProfileUser(models.Model):
    profile_user = models.ForeignKey(ProfileUser, on_delete=models.CASCADE, verbose_name=_('Пользователь'))
    project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name=_('Проект'))
    sections = models.ManyToManyField(Section, through='ProfileUserSection', verbose_name=_('Категории'))


class ProfileUserSection(models.Model):
    project_profile_user = models.ForeignKey(ProjectProfileUser, on_delete=models.CASCADE, verbose_name=_('Пользователь'))
    section = models.ForeignKey(Section, on_delete=models.CASCADE, verbose_name=_('Категория'))
    сriterions = models.ManyToManyField(Criterion, verbose_name=_('Критерии'), through='ProfileUserSectionCriterion')


class ProfileUserSectionCriterion(models.Model):
    criterion = models.OneToOneField(Criterion, on_delete=models.CASCADE, verbose_name=_('Критерий'))
    profile_user_section = models.ForeignKey(ProfileUserSection, on_delete=models.CASCADE, verbose_name=_('Категория'))

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anatoly Scherbakov, 2016-01-24
@beugene

If I understand correctly, each row corresponds to one `ProfileUser`, and each column to one `Section`. And not all, but only those `Section` that belong to the current project. Each cell is therefore the number of all `ProfileUserSection` objects corresponding to the corresponding `ProfileUser` and `Section`. Do I get it right?
Addressing in the template is not possible, this is a deliberate limitation. Therefore, you will have to transfer a ready-made matrix of cells to the template. Well, for example, as follows - I can not vouch for the optimality, however.

sections = list(Section.objects.filter(project=project, ...))
users = list(ProfileUser.objects.filter(...))

cells = [[user] + [
    ProfileUserSection.objects.filter(user=user, section=section).count() for section in sections
] for user in users]

context = {
    'sections': sections,
    'rows': cells
}

Sample:
{% for row in rows %}
<tr>
    {% for cell in row %}
        <td>{{ cell }}</td>
    {% endfor %}
</tr>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question