skip to Main Content

I am currently try make a task manager such that there are folders which have tasks in them, I have been stuck on this problem for hours now and am not sure at all what is the issue

this is urls.py

from django.urls import path
from . import views

app_name= 'tasks'

urlpatterns = [
    path('', views.folders_list,name="list"),
    path('new-folder/', views.folder_new,name="new-folder"),
    path('<slug:slug>', views.tasks_list,name="folder-page"),
    path('<slug:folder_slug>/<int:task_id>/', views.task_page,name="task-page"),
    path('new-task/', views.task_new,name="new-task"),  
]

this is models.py

from django.db import models
from django.contrib.auth.models import User
# from .models import Folder

# Create your models here.
class Folder(models.Model):
  folder_id=models.AutoField(primary_key=True)
  title=models.CharField(max_length=75)
  created=models.DateTimeField(auto_now_add=True)
  slug=models.SlugField()
  author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)

class Task(models.Model):
  PRIORITY_CHOICES=[
    ('LOW','LOW'),
    ('MEDIUM','MEDIUM'),
    ('HIGH','HIGH'),
  ]
  task_id=models.AutoField(primary_key=True)
  title=models.CharField(max_length=75)
  description=models.TextField()
  slug=models.SlugField()
  deadline=models.DateField()
  uploaded=models.DateTimeField(auto_now_add=True)
  author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
  folder = models.ForeignKey('Folder', on_delete=models.CASCADE, default=None)
  priority = models.CharField(max_length=10, choices=PRIORITY_CHOICES, default='LOW')

  def __str__(self):
    return self.title

this is views.py

from django.shortcuts import render,redirect
from django.utils.regex_helper import re
from .models import Task,Folder
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
from . import forms

# Create your views here.

@login_required(login_url="/users/login/")
def folders_list(request):
    user_folders = Folder.objects.filter(author=request.user)
    return render(request, 'tasks/folders_list.html', {'folders': user_folders})

#as folder_page == tasks_list.html
def tasks_list(request, slug):
  # folder=get_object_or_404(Folder,slug=slug)
  folder=Folder.objects.get(slug=slug)
  folder_tasks = Task.objects.filter(folder=folder)
  return render(request, 'tasks/tasks_list.html', {'folder':folder,'tasks': folder_tasks})
    

def task_page(request, folder_slug, task_id):
    folder = get_object_or_404(Folder, slug=folder_slug)
    task = get_object_or_404(Task, pk=task_id, folder=folder)
    return render(request, 'tasks/task_page.html', {'task': task})


def folder_new(request):
  if request.method=='POST':
    form=forms.CreateFolder(request.POST)
    if form.is_valid():
      newfolder=form.save(commit=False)
      newfolder.author=request.user
      newfolder.save()
      return redirect('tasks:list')
  else:
    form=forms.CreateFolder()
  return render(request, 'tasks/folder_new.html', {'form':form})

def task_new(request):
  if request.method=='POST':
    form=forms.CreateTask(request.POST)
    if form.is_valid():
      newtask=form.save(commit=False)
      newtask.author=request.user
      newtask.save()
      return redirect('tasks:list')
  else:
    form=forms.CreateTask()
  return render(request, 'tasks/task_new.html', {'form':form})

I initially tried it with multiple slugs like this

path('<slug:folder_slug>/<slug:task_slug>/', views.task_page,name="task-page"),

then I opted to use task_id instead thinking it was the issue with multiple slugs but nope folder-page i.e.

def tasks_list(request, slug): #in views.py

itself is not rendering and I am getting this error

NoReverseMatch at /tasks/new-folder
Reverse for 'task-page' with keyword arguments '{'folder_slug': 'new-folder', 'task_id': ''}' not found. 1 pattern(s) tried: ['tasks/(?P<folder_slug>[-a-zA-Z0-9_]+)/(?P<task_id>[0-9]+)/\Z']

at this line

<a href="{% url 'tasks:task-page' folder_slug=folder.slug task_id=task.id %}">

in tasks_list.html

{% extends 'layout.html' %}

{% block title %}
    Tasks
{% endblock %}

{% block content %}
  <section>
    <h1> {{folder.title}}</h1>
    <h1>Tasks</h1>

    {% for task in tasks %}
      <article class="task">
          <h2>
            <a href="{% url 'tasks:task-page' folder_slug=folder.slug task_id=task.id %}">
              {{ task.title }}
            </a>
          </h2>
          <p>{{ task.uploaded }} by {{ task.author}}</p>
          <p>{{ task.deadline}}</p>
      </article>
    {% endfor %}
    <form action="{% url 'tasks:new-task' %}" method="post">
      {% csrf_token %}
      <button class="form-submit">New Task</button>
    </form>
 </section>
{% endblock %}

Not sure what to do.

I have tried using this too

def tasks_list(request, slug):
    folder = get_object_or_404(Folder, slug=slug)
    folder_tasks = Task.objects.filter(folder=folder)
    return render(request, 'tasks/tasks_list.html', {'folder': folder, 'tasks': folder_tasks})

2

Answers


  1. Chosen as BEST ANSWER

    I got it working after getting the idea that I could use the task title as a slug instead of the user writing one so

    this is models.py

    from django.utils.text import slugify
    
    class Task(models.Model):
    
    
      task_id=models.AutoField(primary_key=True)
      title=models.CharField(max_length=75)
      .
      .
      .# rest of the attributes
      
      def save(self, *args, **kwargs):
            if not self.slug:
                self.slug = slugify(self.title)
            super(Task, self).save(*args, **kwargs)
    

    CreateTask form to exclude slug from fields

    views.py

    def task_page(request, folder_slug, task_slug):
        folder = get_object_or_404(Folder, slug=folder_slug)
        task = get_object_or_404(Task, slug=task_slug, folder=folder)
        return render(request, 'tasks/task_page.html', {'task': task})
    

    urls.py

    path('<slug:folder_slug>/<slug:task_slug>/', views.task_page,name="task-page")
    

    tasks_list.html

    <a href="{% url 'tasks:task-page' folder_slug=folder.slug task_slug=task.slug %}">
    

  2. In your case, the error message points out that the task_id is empty. This means that at some point in your loop, a task object does not have an id attribute, or the tasks list is empty. please adjust your code with adding if else in your loop to check if task.id exists: here is an example,:

    {% for task in tasks %}
          {% if task.id %}
            <article class="task">
              <h2>
                <a href="{% url 'tasks:task-page' folder_slug=folder.slug task_id=task.id %}">
                  {{ task.title }}
                </a>
              </h2>
              <p>{{ task.uploaded }} by {{ task.author }}</p>
              <p>{{ task.deadline }}</p>
            </article>
          {% else %}
            <article class="task">
              <h2>{{ task.title }}</h2>
              <p>{{ task.uploaded }} by {{ task.author }}</p>
              <p>{{ task.deadline }}</p>
              <p><strong>Error: Missing task ID</strong></p>
            </article>
          {% endif %}
        {% endfor %}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search