Django Reverse / get_absolute_url

I just spent multiple hours trying to figure this out and I hope this helps someone else.

In urls.py

path("//", PostDetail.as_view(), name='post-detail'),
path("/", UserPosts.as_view(), name='user-post-list'),

In [models.py](https://models.py) for the Post model

def get_absolute_url(self):
return reverse("post:post-detail", kwargs={"slug":self.slug, "name":self.user.username})

template:

This works:

{{post.title}}

This also works:

{% for post in post_list %}

{{post.title}}

{% endfor%}

And this DOES NOT WORK: (I spent an embarrassing amount of time trying to figure this out)

{% for post in post_list %}

{{post.title}}

{% endfor%}

Note the difference between {% url %} and {{ }}. The error message looked exactly like what I wanted and it confused me for too long. Looked at too many stack-overflow questions without noticing the difference.

Hope this helps someone else.

2 thoughts on “Django Reverse / get_absolute_url”

  1. Good debugging!

    I once wasted an hour because in the URL path I wrote `/article/{slug:slug}/` and it would just not work! 🙂

    Reply
  2. The `{% url %}` tag is reserved for a URL namespace that uniquely points to a path and its view. There’s slightly more logic going on here.

    When it comes to using `{{ post.get_absolute_url }}`, it inserts the URL path of where the resource is located and the URL is saved when the instance is created. When it comes to using `{{ }}`, you’re asking Django to take some attribute stored in your model instance and inserting it within those double curly braces.

    That’s the difference between `{% %}` and `{{ }}`. You could do:

    * {% url ‘post:post\_detail’ name=name slug=slug %}

    OR

    * {{ post.get\_absolute\_url }}

    Option #2 is just cleaner. No url keyword is needed. I can’t say this definitively, but I think it would be faster as well.

    Reply

Leave a Comment