I am new to Django Class based views. I am trying to make a simple view to get details of a post. My views.py:
from django.views.generic import ListView, View, DetailView
class GenreDetail(DetailView):
model = Post
template_name = "post.html"
My urls.py:
urlpatterns = [
url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
]
Error that I get:
AttributeError at /2/memoirs-of-a-geisha-by-arthur-golden
Generic detail view GenreDetail must be called with either an object pk or a slug.
So the pk or slug is not passed to the Generic Detailview. How do I pass that ? I assume from url it can pick up but it's not.
A Slug is a short label for something, containing only letters, underscores or hyphens. In the url, the slugify-urls-in-django is the slug. This will not work if two posts will have same title, and there are multiple ways of generating unique slugs.
Django DetailView refers to that type of view that shows a single instance from the Model Table. It is used to display the information about a single entry from the database and also to carry out different tasks on that instance.
pk_url_kwarg. The name of the URLConf keyword argument that contains the primary key. By default, pk_url_kwarg is 'pk' . context_object_name. Designates the name of the variable to use in the context.
url patterns are checked in the order you define them
so here:
urlpatterns = [
url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
]
...the first pattern is getting matched (because it does not end with $
so the extra segment is just ignored)
...and that pattern only passes a single keyword arg
Generally it is a bad idea to have multiple url patterns pointing to the same view. If possible you should try and make a single regex (eg using optional groups) which handles the various cases of the url for a particular view. It's more explicit that way.
On the other hand, simply reversing the order of your patterns to put the more explicit one first would also work and be correct (this is the Django rule of urlpatterns!)
urlpatterns = [
url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
]
As @ozgur mentions you also need to tell the view to use post_id
instead of pk
by setting pk_url_kwarg
If you want to fetch details using either post_id or slug then your urls should be like this
url(r'post/(?P<post_id>\d+)/$', GenreDetail.as_view(), name = 'post_detail'),
url(r'post/(?P<slug>[-\w]+)/$', GenreDetail.as_view(), name = 'post_detail_slug'),
And your view should be like this
from django.views.generic import DetailView
class GenreDetail(DetailView):
model = Post
template_name = "post.html"
pk_url_kwarg = "post_id"
slug_url_kwarg = 'slug'
query_pk_and_slug = True
For more details please read the docs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With