Reputation: 334
I'm trying to make an article list view of my homepage which works in two ways.
Here is a part of my app url.py:
path('article_list/<slug:tag>', views.article_list, name='article_list'),
I would like to make this one URL cover both all articles case and tag-specified article case, by making the view shows all articles if slug: tag
is ''
.
Here is a part of my view.py:
def article_list(request, tag):
if tag == '':
articles = get_list_or_404(Article)
else:
articles = get_list_or_404(Article, tags__name__in=[tag], publish=True)
context = {
'tag': tag,
'articles': articles,
}
return render(request, 'blog/article-list.html', context)
Every thing works just fine execpt rethriving all article URL on html with django template {% url %}
tag.
I want something like this:
href="{% url 'article_list' '' %}"
How can I make the URL with an empty argument(in this case, empty slug)?
Upvotes: 4
Views: 1447
Reputation: 476709
The reason this does not work is because the <slug:…>
path converter [Django-doc] matches only non-empty subsequences of the path. Indeed, the class is defined as [GitHub]:
class SlugConverter(StringConverter): regex = '[-a-zA-Z0-9_]+'
There are basically two options here: generate two paths (one for tags, one without tags), or implement a path converter/use a regex.
# app/urls.py
from django.urls import path
from app import views
urlpatterns = [
path('article_list/', views.article_list, name='article_list', kwargs={'slug': ''}),
path('article_list/<slug:tag>', views.article_list, name='article_list'),
]
It might be worth here to implement a path converter yourself:
# app/converters.py
from django.urls.converters import SlugConverter
class EmptyOrSlugConverter(SlugConverter):
regex = '[-a-zA-Z0-9_]*'
Then you can register this and use the <emptyorslug:…>
path converter:
# app/urls.py
from django.urls import path, register_converter
from app import converters, views
register_converter(converters.EmpotyOrSlug, 'emptyorslug')
urlpatterns = [
path('article_list/<emptyorslug:tag>', views.article_list, name='article_list'),
]
Note that you can slightly improve the readability of your view with:
def article_list(request, tag):
if not tag:
articles = get_list_or_404(Article, tags__slug=tag, publish=True)
else:
articles = get_list_or_404(Article)
context = {
'tag': tag,
'articles': articles,
}
return render(request, 'blog/article-list.html', context)
Note that you probably want to filter on the slug
of the tag, not the name
.
Upvotes: 2