Blueice
Blueice

Reputation: 143

Django 1.10: Redirect to another view or url not working. django.urls.exceptions.NoReverseMatch

In Django 1.10, My redirect to other view via url or the viewname is not working.

The main urls.py file is as below:

urlpatterns = [
    url(r'^', include('app1.urls')),
]

The urls.py file inside app1 is:

from django.conf.urls import url

from . import views

app_name = 'app1'
urlpatterns = [
    url(r'^$', views.home, name='home'),
    url(r'^details/$', views.details, name='details'),

]

The views.py for app1 is as below:

from django.shortcuts import render, redirect
from django.utils.timezone import now
import datetime
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse

    def home(request):
        if request.method == 'POST':
            print("redirected from home..................")
            url = reverse('details')
            return HttpResponseRedirect(url)
            # return redirect('app1:details')
            # return redirect('/details/')
            # return redirect('details')
        print("Not redirected..................")
        return render(request, "app1/index.html", {})


    def details(request):
        print("Redirect OK inside details")
        today = datetime.date.today()
        return render(request, "app1/details.html", {
            'today': today,
            'now': now(),
            'email_text': request.POST.get('email_item', 'bla bla'),
        })

I tried all the options in the home view with the commented code like using both HttpResponseRedirect and redirect but not able to redirect to the details view.

I get the error:

    django.urls.exceptions.NoReverseMatch: Reverse for 'details' with
 arguments '()' and keyword arguments '{'request': <HttpRequest>}' not found. 0 pattern(s) tried: []

Any suggestions would help:

Upvotes: 0

Views: 2303

Answers (2)

DragonBobZ
DragonBobZ

Reputation: 2444

I'm sure you found a solution long ago, but I've struggled with this problem before and I came up with a simple solution that doesn't require you to create a view that exists solely to redirect you to another view. Hopefully it helps some people out who need this question answered still. In general, it goes like this:

from django.shortcuts import redirect
urlpatterns = [
    url(r'^$', lambda request: redirect('my_redirect_url_name')),
    url(r'^my_redirect_url/$', views.redirect_view, name='my_redirect_url_name'))
]

I'm not sure why, but this does not work if you only pass redirect(); it must be contained within a function such as a lambda function.

If you want to do something as simple as redirect them to the login page you can use the login_required decorator or another a custom login lambda function:

from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
urlpatterns = [
    url(
         r'^$', 
         login_required(lambda request: redirect('my_redirect_url_name'), 
                               redirect_field_name='my_login_url_name')
    ), 
    # this custom redirect function will behave like login_required()
    url(
        r'^$', 
        lambda request: redirect('my_redirect_url_name') if request.user and \
            request.user.is_authenticated() else redirect('my_login_url_name')
    ),
    url(r'^my_redirect_url/$', views.redirect_view, name='my_redirect_url_name')),
    url(r'^my_login_url/$', views.login_view, name='my_login_url_name'))
]

Specifically in answer to your question, I think this will give the redirect you want. This in urls:

from django.shortcuts import redirect
urlpatterns = [
    url(
        r'^$', 
        lambda request: redirect('index') if request.method == 'POST' else \ 
                        redirect('details'),
        name='home'
    ),
    url(r'^details/$', views.details, name='details'),
    url(r'^index/$', views.index, name='index'),
]

With this added to views:

def index(request):
    return render(request, "app1/index.html", {})

Just FYI, I have not tested this with a redirect using if request.method == 'POST', but I think it will work.

Upvotes: 2

Keith Bailey
Keith Bailey

Reputation: 296

Note the working example within your own code.

By specifying the app name you need to use namespacing with reverse.

reverse('details')

should read

reverse('app1:details')

See the documentation over here: https://docs.djangoproject.com/en/1.10/ref/urlresolvers/

Upvotes: 1

Related Questions