Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to limit the number of responses to my for loop to 3 in Django Templates?

In my current Django template I have two models in use, which are defined in my views.py as:

'tasks' : IndividualTask.objects.all(),
'updates' : TaskUpdate.objects.all(),

I have set up signals so that when there is an update to a task, an update is created.

Currently, I iterate through each task, then each of their updates and pull out the relevant updates for each task, as shown below.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{% for task in tasks %}
{% for update in updates %} 
    {% if task.id == update.task.id %}
        {{ update.update }}
    {% endif %}
{% endfor %} 
{% endfor %} 

However, I would like to limit the number of updates I show to three.

I have tried using slice, show below, but this limits all updates to the top 3 of all updates as opposed to the top 3 of each individual task’s updates.

{% for task in tasks %}
{% for update in updates|slice:":3" %} 
    {% if task.id == update.task.id %}
        {{ update.update }}
    {% endif %}
{% endfor %} 
{% endfor %}

Models.py is as below:


class IndividualTask(models.Model):
    task = models.CharField( 
        max_length = 256,
        blank=False,
        null=True,
        )

    task_description = models.CharField(
        max_length = 256,
        blank=False,
        null=True,
        )

    expected_completion = models.DateField(
        max_length = 64,
        null=True,
        )

    goal = models.ForeignKey(
        IndividualGoal,
        on_delete=models.CASCADE,
        related_name="goals",
        blank=False,
        null=True,
    )

    creator = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="creator",
        blank=False,
        null=True,
    )

    owner = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        blank=False,
        null=True,
    )


    status_choices = [
        ("", "Select Current Status"),
        ("Preparation", "Preparation"),
        ("Review", "Review"),
        ("Update", "Update"),
        ("Finalised", "Finalised"),
    ]

    current_status = models.CharField(
        max_length=32,
        choices = status_choices,
        default = "Select current status",
    )

    created = models.DateField(
        auto_now_add = True,
    )

    def __str__(self):
        return f"{self.task}"

class TaskUpdate(models.Model):
    update = models.CharField(
        max_length = 5000,
    )

    task = models.ForeignKey(
        IndividualTask,
        on_delete=models.CASCADE,
        null = True,
    )

    update_created = models.DateField(
        auto_now_add = True,
    )

    update_time_created = models.TimeField(
        auto_now_add = True,
    )

    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="update_author",
        blank=True,
        null=True,
    )

    update_choices = [
        ("New Task", "New Task"),
        ("New Commentary", "New Commentary"),
    ]

    update_status = models.CharField(
        max_length=32,
        choices = update_choices,
        null = True,
    )

    class Meta:
        ordering = ["-update_created", "-update_time_created"]

I would be grateful for any advice as to how I can limit the number of updates shown for each task to 3 please?

EDIT:

Full traceback shown below:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/tasks/

Django Version: 4.0.2
Python Version: 3.9.10
Installed Applications:
['tasks.apps.TasksConfig',
 'notes',
 'accounts',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /Users/Tom/Desktop/squeasy/tasks/templates/tasks/tasks.html, error at line 69
   'RelatedManager' object is not iterable
   59 :                         Expected Completion Date
   60 :                     </div>
   61 :                     <div class = expected_completion>
   62 :                     {{ task.expected_completion }}
   63 :                     </div>
   64 :                 </div>
   65 :             </div>
   66 :             <div class = task_sub_header>
   67 :                 Latest updates:
   68 :             </div>
   69 :                  {% for update in task.taskupdate_set|slice:":3" %} 
   70 :                     {% if task.id == update.task.id %}
   71 :                     <div class = individual_update>
   72 :                         {% if update.update_status == "New Task" %}
   73 :                             {{ update.author }} created this task on {{ update.update_created|date:"l jS F" }} at {{ update.update_time_created|time:"H:i" }}
   74 :                         {% elif update.update_status == "New Commentary" %}
   75 :                             {{ update.author }} updated the commentary for {{ update.task }} on {{ update.update_created|date:"l jS F" }} at {{ update.update_time_created|time:"H:i" }}
   76 :                         {% endif %}
   77 :                     </div>
   78 :                     {% endif %}
   79 :                 {% endfor %} 


Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/Tom/Desktop/squeasy/tasks/views.py", line 28, in tasks
    return render(request, "tasks/tasks.html", context)
  File "/usr/local/lib/python3.9/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 176, in render
    return self._render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 168, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 977, in render
    return SafeString(''.join([
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 153, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 168, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 977, in render
    return SafeString(''.join([
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/loader_tags.py", line 65, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 977, in render
    return SafeString(''.join([
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 298, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 977, in render
    return SafeString(''.join([
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 217, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 217, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 298, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 977, in render
    return SafeString(''.join([
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File "/usr/local/lib/python3.9/site-packages/django/template/base.py", line 938, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.9/site-packages/django/template/defaulttags.py", line 173, in render
    values = list(values)

Exception Type: TypeError at /tasks/
Exception Value: 'RelatedManager' object is not iterable

>Solution :

In the context you can pass the IndividualTasks with the TaskUpdates ordered in descending order with a Prefetch object [Django-doc]:

from django.db.models import Prefetch

context = {
    'tasks' : IndividualTask.objects.prefetch_related(
                  Prefetch('taskupdate_set', TaskUpdate.objects.order_by('-update_created', '-update_time_created'))
              )
}

then in the template you enumerate over the taskupdate_set:

{% for task in tasks %}
    {% for update in task.taskupdate_set.all|slice:":3" %} 
        {{ update.update }}
    {% endfor %}
{%endfor %}

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading