Home > OS >  The usage of {% url ...%} vs {{ ... }} in Django templates
The usage of {% url ...%} vs {{ ... }} in Django templates

Time:10-06

I've been practicing Djnago and for that, I was building a blog. While in the process of building it, I was faced with an error, while using the following code:

<a href="{% url 'blog_post' post.slug %}">
    {{ post.title }}
</a>

While studying and doing other courses something like this would work fine. But now, it will raise this exception: NoReverseMatch.

If I use this code though, it will work just fine:

<a href="{{ post.slug }}">
    {{ post.title }}
</a>

While working in different projects the first way would work fine, but this time, it doesn't.

My question is why?

Here is the code in my urls and on my views. Maybe the mistake is here, not somewhere else.

If anyone can explain why this is happening, or where I'm going wrong, it will be greatly appreciated

urls:

from django.urls import path

from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.blog_index, name='blog_index'),
    path('<slug:post_slug>/', views.blog_post, name='blog_post'),
]

views:

from django.shortcuts import render
from .models import Post

# Create your views here.
def blog_index(request):
    posts = Post.objects.order_by('- 
    created').filter(published=True)
    data = {
        'posts': posts
    }
    return render(request, 'blog/post_list.html', data)

def blog_post(request, post_slug):
    post = Post.objects.get(slug=post_slug)
    data = {
        'post': post
    }
    return render(request, 'blog/post_detail.html', data)

CodePudding user response:

try this.your problem is that you have a namespace in your urls.py then in your href you should add that namespace('blog').

<a href="{% url 'blog:blog_post' post.slug %}">
    {{ post.title }}
</a>

this

 <a href="{{ post.slug }}">
    {{ post.title }}
</a>

this code above was working because you are located inside the home page and when you add this(href="{{ post.slug }}" in the a tag) it will just call the current url "/<'slug:post_slug/' and this is a valid url.but this is a very bad option.use the the first option.
to learn about this refer to this https://docs.djangoproject.com/en/3.2/topics/http/urls/#url-namespaces.

CodePudding user response:

In such cases, you should use: https://docs.djangoproject.com/en/3.2/ref/models/instances/#get-absolute-url The less logic in the templates, the better for the application. It is difficult to write tests on logic that is contained in templates.

You should add a method to your model:

from django.urls import reverse

class Post()
    ...
    def get_absolute_url(self):
        return reverse('blog:blog_post', kwargs={'post_slug' : self.slug})

In the reverse function you need to add an application namespace. In your case, it's a blog. https://docs.djangoproject.com/en/3.2/topics/http/urls/#introduction

and then in template use:

{{ post.get_absolute_url }}

From documentation:

The logic here is that if you change the URL structure of your objects, even for something small like correcting a spelling error, you don’t want to have to track down every place that the URL might be created. Specify it once, in get_absolute_url() and have all your other code call that one place.

  • Related