'django.urls.exceptions.NoReverseMatch: Reverse for 'new_entry' with arguments '(1,)' not found. 1 pattern(s) tried: ['new_entry/$']

I am currently working on a tutorial in the "Python Crash course" Book.

The tutorial is about creating a "Learning Log" Webapp with Django. The idea of the app is to allow users to: 1. create "Topics" they have learned about 2. add "Entries" to those Topics, describing details they have learned specific to those topics

I am currently stuck at editing an existing Entry form and receive an Error, when I run http://127.0.0.1:8000/topics/2/

forms.py file

    from django import forms
    from .models import Topic,Entry
    class Topicform(forms.ModelForm):
         class Meta:
         model = Topic
         fields =['text']
         labels = {'text' :''}
    class Entryform(forms.ModelForm):
        class Meta:
        model = Entry
        fields =['text']
        labels = {'text' :''}
        widgets = {'text' : forms.Textarea(attrs={'cols':80})}

urls.py file

    from django.conf.urls import url
    from . import views
    app_name='learning_logs' 
    urlpatterns=[
      #Home page
    url(r'^$',views.index,name='index'),
      #Show all topics page
    url(r'^topics/$',views.topics,name='topics'), 
      #Detail page for a single topic
    url(r'^topics/(?P<topic_id>\d+)/$',views.topic,name='topic'),
      #Page for adding a new topic
    url(r'^new_topic/$',views.new_topic,name='new_topic'),
      #Page for adding a new entry
    url(r'^new_entry/$',views.new_entry,name='new_entry'),
      #Page for editing an entry
    url(r'^edit_entry/(?P<entry_id>\d+)/$',views.edit_entry,name='edit_entry'), 

]

views.py file

    from django.http import HttpResponseRedirect
    from django.urls import reverse
    from django.shortcuts import render
    from .models import Topic,Entry 
    from .forms import Topicform, Entryform
    --snip--
    def edit_entry(request,entry_id):
        entry = Entry.objects.get(id=entry_id)
        topic=entry.topic

        if request.method != 'POST':
        # No data submitted; create a blank form
           form = Entryform(instance = entry)
        else:
        # Post data submitted;process data
           form = Entryform(request.POST,instance=entry)
           if form.is_valid():
                form.save()
        return HttpResponseRedirect(reverse('learning_logs:topics',args=[topic.id]))

   context={'entry':entry,'topic':topic,'form':form}
   return render(request,'learning_logs/edit_entry.html',context)

edit_entry.html file

    {% extends "learning_logs/base.html" %}

    {% block content %}

    <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>

    <p>Edit Entry:</p>
    <form action= "{%url 'learning_logs:edit_entry' entry.id %}" method = 'post'>
        {%csrf_token %}
        {{form.as_p}}
    <button name="submit">save changes</button>
    </form>

   {% endblock content %}

topic.html file

    {% extends "learning_logs/base.html" %}

    {% block content %}
    <p> Topic: {{topic}} </p>
    <p> Entries:</p>
    <p>
       <a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>
    </p>
    <ul>
         {%for entry in entries%}
       <li>
         <p> {{entry.date_added|date:'M d,Y H:i'}} </p>
         <p> {{entry.text|linebreaks}} </p>
         <p>
            <a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a>
         </p>
      </li>
  {%empty%}
      <li>
         There are no entries for this topic yet.
      </li>
 {% endfor %} 
 </ul>
{% endblock content %}


Solution 1:[1]

Your new_entry path does not take any parameter as from your urls.py. But you gave one, in topic.html:

<a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>

Here, topic.id is what you gave. But should be:

<a href="{% url 'learning_logs:new_entry' %}">Add new entry</a>

EDIT

So, I ll try to explain. Firstly, Let you see the url for new_entry as you register in urls.py.

  #Page for adding a new topic
  url(r'^new_topic/$',views.new_topic,name='new_topic'),

Here, you did not gave parameter to the path. See, first part of path. r'^new_topic/$'. And, see your url route where you gave the parameter:

  #Page for editing an entry
  url(r'^edit_entry/(?P<entry_id>\d+)/$',views.edit_entry,name='edit_entry'), 

Now, let's see the first part r'^edit_entry/(?P<entry_id>\d+)/$', here you can see parameter, i.e, (?P<entry_id>\d+) with name, entry_id. Comparing both the urls, your practical urls will look like:

  #For adding new topic
  www.example.com/new_topic/

  #For url with parameter
  www.example.com/edit_entry/1/   # 1 is entry_id, parameter for route edit_entry

Now, lets come in your template:

<a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>

See, last part in django url tag, i.e, topic.id. As, in your urls.py you did not give parameter to new_entry. So, if you give parameter to the url which does not take parameter(does not take parameter, I mean to say url is registered but parameter is not set to them), then the url you are getting will be shown.

I hope you now understand what I was saying. For, further more explanation of what to do, you can see the second answer by W-liamx. Have a look at this beautiful documentation on urls by django.

Solution 2:[2]

Adding to Biplove's answer, In your views.py file, Your topics path doesn't take any parameters. May have been a silly typo due to the way you named your urls

So, if you want to return to the list of topics after editing, you should change

return HttpResponseRedirect(reverse('learning_logs:topics',args=[topic.id]))

To

return HttpResponseRedirect(reverse('learning_logs:topics')

But if you want to return to the topic you just edited, you should do this then...

return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2