skip to Main Content

Alright, let me give you guys an example;

We have the following url configuration in Django.

Django will try to match the url with the rules down below. Once it finds a match, it will use the appropriate view and lookup the object in the model.

The thing is, once it finds a match in the URL pattern, it will match the view. But once the object
in the view can’t be found, it will return a page not found (404) error.

urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('articles/<slug:category>/<slug:editor>/', views.ArticleByThemeView.as_view(), name='articles_by_editor'),
    path('articles/<slug:category>/<slug:theme>/', views.ArticleDetailView.as_view(), name='articles_by_theme')
]

views.py

class ArticleByThemeView(ListView):
    """
    List all articles by a certain theme; "World War 2".
    """
    model = Article
    
    def dispatch(self, request, *args, **kwargs):
        try:
            # Check if the theme_slug matches a theme
            theme = ArticleTheme.objects.get(slug=self.kwargs['theme_slug'])
        except ArticleTheme.DoesNotExist:
            # Theme does not exist, slug must be an article_slug
            return redirect(
                'article_detail',
                category_slug=category_slug
                article_slug=theme_slug
            )
        return super().dispatch(request, *args, **kwargs)

class ArticleDetailView(DetailView):
    """
    Detailview for a certain article
    """
    model = Article

    def get_object(self):
        return get_object_or_404(
            Article,
            category__slug=self.kwargs['category_slug'],
            slug=self.kwargs['article_slug']
        )

We have the following url patterns, we can sort articles either by the editor or by theme. We do this to create a logical url structure for SEO purposes.

Is their any way we can redirect to another view once the object isn’t found?

Can we modify the dispatch method to return to the url patterns and find the following matching rule?

2

Answers


  1. Chosen as BEST ANSWER

    Alright,

    Based on the suggestion from Sunderam Dubey, I'wrote a function view, which uses two differn routes to the same view.

    urls.py

    from django.urls import path
    
    from . import views
    
    urlpatterns = [
        path('articles/<slug:category>/<slug:slug>/', views.article_theme_or_detail_view, name='article_by_theme'),
        path('articles/<slug:category>/<slug:slug>/', views.article_theme_or_detail_view, name='article_detail')
    

    ]

    views.py

    def article_theme_or_detail_view(
        request,
        category_slug,
        slug=None
    ):
        """
        This view could either be for a theme view or detailview,
        depending on the slug.
        """
        try:
            # Check if the slug represents a theme
            theme = ArticleTheme.objects.get(slug=slug)
            article_list = Article.object.filter(theme=theme)
            
            # Add context
            context = {
                'theme': theme,
                'article_list': article_list
            }
    
            # Render the template with context
            return render(
                request,
                'article_by_theme.html',
                context
            )
        except ArticleTheme.DoesNotExists:
            # The theme does not exist so the slug must be for a detail view
            context = {
                article = Article.objects.get(slug=slug)
            }
    
            return render(
                request,
                'article_detail.html',
                context
            )
    

    Todo:

    • Remove one of the url routes

  2. What about redirection like this:

    def articles_by_editor(request, category, editor):
        try:
            article = Article.objects.get(category=category, editor=editor)
            # return article
        except Article.DoesNotExist:
            # redirect to another view
            return redirect('articles_by_theme', category=category)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search