Search code examples
pythondjangoslug

404 on slug in django


I am following a tutorial where they do something like this:

<a href="{ % url 'films:add_comment' slug=film.slug %}">Leave a comment</a>

They use slug. I have not been doing that, but have been referencing an ID. The parts of my code which I think are important to this are:

films/urls.py:

from django.conf.urls import url
from django.urls import path
from . import views


    app_name = 'films'
    urlpatterns = [
        path('', views.index, name='index'),
        url(r'^films/<int:film_id>/comment/', views.add_comment, name='add_comment'),
        path('films/<int:film_id>/', views.detail, name='detail'),
    ]

films/views.py

def add_comment(request, film_id):
    film = get_object_or_404(Film, pk=film_id)
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit = False)
            comment.post = post
            comment.save()
            return redirect('film:detail',film)
    else:
        form = CommentForm()
        template = 'films/add_comment.html'
        context = {'form':form}
        return render (request,template,context)

mysite/urls.py:

urlpatterns = [
    url(r'^accounts/',include('accounts.urls')),
    url(r'^', include('films.urls')),
    url(r'^admin/', admin.site.urls),
]

add_comment.html:

{% extends 'base_layout.html' %}
{% block content %}

<div class="create-comment">
    <h2>Add Comment</h2>

</div>

{% endblock %}

If I click the link I made which is: <a href="{ % url 'films:add_comment' film.id %}">Leave a comment</a>

I get this: enter image description here

And if I manually alter the url to

http://127.0.0.1:8000/films/2/comment/

I get this:

enter image description here

But it looks like url 3 in that list matches what I typed?


Solution

  • you are so close. Just some minor mistakes I believe:

    (Final Working Edit)

    films/urls.py

    urlpatterns = [ 
       path('', views.index, name='index'), 
       path('<int:film_id>/comment', views.add_comment, name='add_comment'), 
       path('<int:film_id>', views.detail, name='detail'), 
    ]
    

    mysite/urls.py

    urlpatterns = [ 
       url('films/', include('films.urls')), 
       url('accounts/',include('accounts.urls')), 
       url('admin/', admin.site.urls), 
    ]
    

    (Working out)


    films/urls.py:

    app_name = 'films'
    urlpatterns = [
       url(r'^films/(?P<film_id>\d+)/comment/', views.add_comment, name='add_comment'),
    ]
    

    Notice: (?P<film_id>\d+) that's how you capture the correct identifier


    This is incorrect:

    <a href="{ % url 'films:add_comment' film.id %}">Leave a comment</a>

    It should be:

    <a href="{% url 'films:add_comment' film_id=film.id %}">Leave a comment</a>

    • Notice there is no gap in {%
    • and we now use the identifier we defined in urls.py above.

    Your def add_comment(request, film_id): has me a tad confused, however give my suggestions a shot. Then comment with any issues that occurred and we'll solve this!


    EDIT: Ok next mini-errors that might be holding you back

    urlpatterns = [
        path(r'^$', views.index, name='index'),
        path(r'^films/<int:film_id>/comment/$', views.add_comment, name='add_comment'),
        path(r'^films/<int:film_id>/$', views.detail, name='detail'),
    ]
    
    • Make all the first arg strings regex strings i.e. 'foo' -> r'foo'
    • According to the v2 release notes, you need to use path( ) to use your cool <int:film_id> syntax. url() will not do it sadly ☹️
    • End your regexes with a '$', it means end of string. Prevents matching films/2/comment to films/2/