pythondjangoproject-managementtask-management

Listing my tasks under my projects in Django


I am new to Django (and programming in general) and could use help with something possible very simple but I can't figure it out.

Currently I am working on a Project Manager app in Django for my portfolio.

But I am stuck with creating list of the different project and their tasks.

I would like to create something like this:

Project_1

  1. task item 1 (of project_1)
  2. task item 2 (of project_1)

Project_2

  1. task item 1 (of project_2)
  2. task item 2 (of project_2)

Project_3

  1. task item 1 (of project_3)
  2. task item 2 (of project_3)
  3. task item 3 (of project_3)

Currently I have the following:

view.py:

def project(request):
""" Show all Projects"""
projects = Project.objects.order_by('date_added')
project = Project.objects.get(id=1)
tasks = project.task_set.order_by('date_added')
context = {'projects': projects, 'tasks': tasks}
return render(request, 'tasks/project.html', context)

project.html

    {% extends "tasks/base.html" %}
{% block content %}
<p>Projects</p>
<ul>
    {% for project in projects %}
    <li>{{project}}</li>
        <ul>
            {% for task in tasks %}
            <li>{{task}}</li>
            {% empty %}
            <li>No tasks added </li>
            {% endfor %}
        </ul>
    {% empty %}
    <li>No projects have been added yet.</li>
    {% endfor %}
</ul>

{% endblock content %}

models.py

class Project(models.Model):
    """A project the user is working on."""
    text = models.CharField(max_length=200)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        """Return a string representation of the model."""
        return self.text


class Task(models.Model):
    """A task of a project to complete."""
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = 'tasks'

    def __str__(self):
        """Return a string representation of the model."""
        if(len(self.text) < 50 ):
            return f"{self.text}"
        else:
            return f"{self.text[:50]}..."

The result I get is:

Project_1

  1. task item 1 (of project_1)
  2. task item 2 (of project_1)

Project_2

  1. task item 1 (of project_1)
  2. task item 2 (of project_1)

Project_3

  1. task item 1 (of project_1)
  2. task item 2 (of project_1)

I know the issue is that I use project = Project.objects.get(id=1) and because of this it only shows the tasks related to project one. And I think if the id is related to the right project id this might be the solution. I don't seem to find out how I do this. Or I might be looking in the wrong direction.

Any help is welcome, thanks for in advance.


Solution

  • You should be able to use the reverse lookup for the task from project. See this part of the django docs for it: https://docs.djangoproject.com/en/3.0/topics/db/queries/#following-relationships-backward

    You have established a foreign key relationship from Tasks to Project. So one project has many tasks. You can access the tasks of a project using the reverse lookup using project.task_set reference. You can do this in the template as well. So your view would be simply:

    def project(request):
       """ Show all Projects"""
       projects = Project.objects.order_by('date_added')
       context = {'projects': projects}
       return render(request, 'tasks/project.html', context)
    

    and the part in your template where you list the tasks should be:

                {% for task in project.task_set.all %}
                <li>{{task}}</li>
                {% empty %}
                <li>No tasks added </li>
                {% endfor %}
    
    

    Hope this helps, please let me know if anything needs to be clarified.