Search code examples
pythondjangodjango-viewsdjango-urlsdjango-settings

Python + Django URL & View errors when attempting to POST to_do item


This is my first attempt at utilizing Django and I've run into an issue with the URL & Views files. I created a project called "reading". Within that project, I created two apps, "products" and "speech". Within the "speech" urls.py file, I have the following code:

from django.urls import path
from speech.views import todoView, addTodo

urlpatterns = [

    path('todo/', todoView),
    path('addTodo/', addTodo)

]

In the views.py file I have the following code:

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from .models import TodoItem

def todoView(request):
    all_todo_items = TodoItem.objects.all()
    return render(request, 'todo.html',
        {'all_items': all_todo_items})

def addTodo(request):
    new_item = TodoItem(content = request.POST['content'])
    new_item.save()
    return HttpResponseRedirect('/todo/')

In the project folder, within the urls.py file, I have:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('products/', include('products.urls')),
    path('speech/', include('speech.urls'))

In the project folder, within the "templates" directory, I have a "todo.html" file with:

<h1>This is the todo page</h1>

<ul>
    {% for todo_item in all_items %}
    <li>{{ todo_item.content}}</li>
    {% endfor %}
</ul>

<form action="/addTodo/" method="POST">{% csrf_token %}
    <input type="text" name="content" />
    <input type="submit" value="Add" />
</form>

When I attempt to add an item to the todo model, I get this error "The current path, addTodo/, didn't match any of these". I tried prepending "speech" to the form such as:

<form action="speech/addTodo/" method="POST">{% csrf_token %}

however, I now get this error:

The current path, speech/todo/speech/addTodo/, didn't match any of these.

Why is it duplicating the path when I prepend "speech" to the /addTodo action?

Not sure if this is associated to the error, but before I implemented a project level "templates" directory, I gave each app its own "templates" directory. Within those directories, I created an "index.html" file with separate content. When I had an index path for each apps, I couldn't get the apps to render the "index.html" file that was associated to it. Instead, it seemed the second application tried to render the "index.html" file of the first app. Is there a top down rule when it comes to templates in Django?


Solution

  • You missed a slash

    Try this:

    <form action="/speech/addTodo/" method="POST">{% csrf_token %}
    

    A more 'Django' way of doing this could be:

    from django.urls import path
    from speech.views import todoView, addTodo
    
    urlpatterns = [
    
        path('todo/', todoView),
        path('addTodo/', addTodo, name='add-todo')
    
    ]
    

    Then in the template:

    <form action="{% url 'add-todo' %}" method="POST">{% csrf_token %}