Ayman Farhat
Ayman Farhat

Reputation: 2090

Get Absolute URL in Django when using Class Based Views

Hello I am migrating my app to use class based views instead of function based views. In my old code I was able to get the absolute URL of an object related to a function view this way:

class Category(models.Model):
    name = models.CharField(max_length=100,unique=True)
    slug = models.SlugField(unique=True)
    description = models.TextField()
    parent = models.ForeignKey('self',null=True,blank=True)

    def get_absolute_url(self):
        return reverse('blog.views.showcategory',args=[str(self.slug)])

I couldn't find what I should change in my get absolute url function in order to get the same result.

This is my new class based view

class CategoryView(ListPosts):
    template_name = "postlist.html"
    context_object_name="posts"
    def get_queryset(self):
         return Post.objects.filter(category__slug=self.kwargs['slug']).order_by('created')

Thanks!

Upvotes: 11

Views: 29839

Answers (5)

nmu
nmu

Reputation: 1519

The 2018 answer to this question is basically the same as @Aaron's, but for quick access here it is:

def get_absolute_url(self):
    from django.urls import reverse
    return reverse('people.views.details', args=[str(self.id)])

From https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url

Upvotes: 3

Arun
Arun

Reputation: 2003

Here is how you do it in Django >= 2.0.

In urls.py

from django.urls import path

app_name = 'my_app'

urlpatterns = [
    path('products/<slug:slug>', views.ProductDetailView.as_view(), name='products')
]

Add the following code to your models.py

class Product(models.Model):
    name = models.CharField(max_length=125)
    slug = models.SlugField(unique=True)
    # rest of the fields

   def get_absolute_url(self):
         return reverse('my_app:products', kwargs={'slug': self.slug})

For displaying the detail, add a generic view in your views.py

class ProductDetailView(DetailView):
     template_name = 'my_app/detail.html'

     def get_queryset(self):
         return Product.objects.all()

Upvotes: 0

Mohamed Ali Mimouni
Mohamed Ali Mimouni

Reputation: 131

This function worked for me, it uses multiple parameters:

def get_absolute_url(self):
return reverse('video', kwargs={'slug':self.chapiter.course.slug,'chpiter_slug':self.chapiter.chpiterSlug,'pk':str(self.index).zfill(2)})

Upvotes: 0

Aaron Lelevier
Aaron Lelevier

Reputation: 20848

Here is my get_absolute_url configuration:

urls.py

urlpatterns = patterns('',
    url(r'^products/(?P<slug>[\w\d\-\_]+)/$', views.ProductView.as_view(), name='product'),
    )

models.py

def get_absolute_url(self):
    return reverse('products:product', kwargs={'slug':self.slug})

My urls.py is under the "products" app, so the url namespace is "products:product"

Upvotes: 12

Daniel Roseman
Daniel Roseman

Reputation: 600059

You should always give your URLs a name, and refer to that:

url(r'/category/(?P<slug>\w+)/$', CategoryView.as_view(), name='category_view'),

Now:

@models.permalink
def get_absolute_url(self):
    return ('category_view', (), {'slug': self.slug})

Note I've used the permalink decorator, which does the same as calling reverse but is a bit neater.

Upvotes: 25

Related Questions