简体   繁体   中英

Django NoReverseMatch Error during Template Rendering

I am setting up a simple blog site with Django, and run into this error when trying to link to a page that allows users to edit existing blog posts.

Reverse for 'edit_post' with arguments '('',)' not found. 1 pattern(s) tried: ['edit_post/(?P<title_id>[0-9]+)/$']

If I understand this error correctly, it means that Django can't find a urlpattern that matches the url being requested. To my eyes I have the urlpattern set up correctly, but I still get the error.

The link in question appears on the text.html template, which is the template that displays the text of a particular blog post.

Here is the relevant code:

urls.py

"""Defines URL patterns for blogs."""

from django.urls import path

from . import views

app_name = 'blogs'
urlpatterns = [
    # Home page, shows all posts in chronological order.
    path('', views.index, name='index'),
    # A page to show the text of a specific post.
    path('text/<int:title_id>/', views.text, name='text'),
    # Page for adding a new post.
    path('new_post/', views.new_post, name='new_post'),
    # Page for editing a post.
    path('edit_post/<int:title_id>/', views.edit_post, name='edit_post'),
]

views.py

from django.shortcuts import render, redirect

from .models import BlogPost 
from .forms import BlogPostForm

def index(request):
    """The home page for blogs, shows all posts."""
    titles = BlogPost.objects.order_by('date_added')
    context = {'titles': titles}
    return render(request, 'blogs/index.html', context)

def text(request, title_id):
    """Show a single post title and its text."""
    title = BlogPost.objects.get(id=title_id)
    text = title.text
    context = {'title': title, 'text': text}
    return render(request, 'blogs/text.html', context)

def new_post(request):
    """Add a new post."""
    if request.method != 'POST':
        # No data submitted; create a new form.
        form = BlogPostForm()
    else:
        # POST data submitted; process data.
        form = BlogPostForm(data=request.POST)
        if form.is_valid():
            new_post = form.save(commit=False)
            new_post.save()
            return redirect('blogs:index')

    # Display a blank or invalid form.
    context = {'form': form}
    return render(request, 'blogs/new_post.html', context)

def edit_post(request, title_id):
    """Edit an existing post."""
    post = BlogPost.objects.get(id=title_id)

    if request.method != 'POST':
        # Initial request: pre-fill form with the current post.
        form = BlogPostForm(instance=post)
    else:
        # Post data submitted; process data.
        form = BlogPostForm(instance=post, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('blogs:index')

    context = {'post': post, 'form': form}
    return render(request, 'blogs/edit_post.html', context)

index.html (this is the homepage for the blog)

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

{% block content %}
<p>Blog is a generic site for a blogger to post content for their audience.</p>

    <p>Posts</p>

    <ul>
        {% for title in titles %}
            <li>
                <a href="{% url 'blogs:text' title.id %}">{{ title }}</a>
            </li>
        {% empty %}
            <li>No posts have been added yet.</li>
        {% endfor %}
    </ul>

    <a href="{% url 'blogs:new_post' %}">Create a new post</a>

{% endblock content %}

text.html (this page displays the text content of a particular post, and also the link to edit the post)

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

{% block content %}

    <p>Title: {{ title }}</p>

    <p>{{ text }}</p>

    <a href="{% url 'blogs:edit_post' title.id %}">Edit post</a>

{% endblock content %}

edit_post.html (this page should display the existing post and allow it to be edited)

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

{% block content %}
    
    <p>Edit post:</p>

    <p>Title:</p>

    <form action="{% url 'blogs:edit_post' title.id %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">Save changes</button>
    </form>

{% endblock content %}

How the edit_post function in views.py should work (in theory) is to create an instance based upon the post's title id, and then allowing the user to edit it and save changes.

I'm not sure where I'm going wrong here and any suggestions are greatly appreciated.

The name of the post object you pass to the template, is not title , but post :

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

{% block content %}
    
    <p>Edit post:</p>

    <p>Title:</p>

    <form action="{% url 'blogs:edit_post'  %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">Save changes</button>
    </form>

{% endblock content %}

If you use title.id , it will not find that variable, and thus this will be resolved to the empty string. If you use post.id , or post.pk , it will resolve to the .id field, or primary key of the post object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM