Redirect while passing message in django

Hanny picture Hanny · Jun 27, 2017 · Viewed 7.9k times · Source

I'm trying to run a redirect after I check to see if the user_settings exist for a user (if they don't exist - the user is taken to the form to input and save them).

I want to redirect the user to the appropriate form and give them the message that they have to 'save their settings', so they know why they are being redirected.

The function looks like this:

def trip_email(request):
    try:
        user_settings = Settings.objects.get(user_id=request.user.id)
    except Exception as e:
        messages.error(request, 'Please save your settings before you print mileage!')
        return redirect('user_settings')

This function checks user settings and redirects me appropriately - but the message never appears at the top of the template.

You may first think: "Are messages setup in your Django correctly?"

I have other functions where I use messages that are not redirects, the messages display as expected in the template there without issue. Messages are integrated into my template appropriately and work.

Only when I use redirect do I not see the messages I am sending.

If I use render like the following, I see the message (but of course, the URL doesn't change - which I would like to happen).

def trip_email(request):
    try:
        user_settings = Settings.objects.get(user_id=request.user.id)
    except Exception as e:
        messages.error(request, 'Please save your settings before you print mileage!')
        form = UserSettingsForm(request.POST or None)
        return render(request, 'user/settings.html', {'form': form})

I have a few other spots where I need to use a redirect because it functionally makes sense to do so - but I also want to pass messages to those redirects.

The user_settings function looks like this:

def user_settings(request):
    try:
        user_settings = Settings.objects.get(user_id=request.user.id)
        form = UserSettingsForm(request.POST or None, instance=user_settings)
    except Settings.DoesNotExist:
        form = UserSettingsForm(request.POST or None)
    if request.method == 'POST':
        settings = form.save(commit=False)
        settings.user = request.user
        settings.save()
        messages.warning(request, 'Your settings have been saved!')

    return render(request, 'user/settings.html', {'form': form})

I can't find anything in the documentation saying that you can't send messages with redirects... but I can't figure out how to get them to show.

Edit: This is how I render the messages in the template:

{% for message in messages %}
  <div class="alert {{ message.tags }} alert-dismissible" role="alert">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
    {{ message }}
  </div>
{% endfor %}

I'm not sure if it matters - but it looks like it's almost calling 'GET' twice from somewhere.

is calling get twice like this normal?

the URL section looks like this for these two URLS:

# ex: /trips/email
url(r'^trips/email/$', views.trip_email, name='trip_email'),
# ex: /user/settings
url(r'^user/settings/$', views.user_settings, name='user_settings'),

Answer

Rudresh Panchal picture Rudresh Panchal · Jun 27, 2017

You cannot view the error message, because it is not getting rendered, and hence there is nowhere for the message to go. The best way to do something like this would be to render an intermediate page, which would display the error message, and redirect after timeout, something of the sort used by payment gateways while redirecting you to your bank.

You can do something like this:

def trip_email(request):
    try:
        user_settings = Settings.objects.get(user_id=request.user.id)
    except Exception as e:
        return render(request, 'no_setting_error.html', {'form': form})

and on the no_setting_error html page, insert Javscript to automatically redirect you after a timeout like:

<script>
    function redirect(){
       window.location.href = "/user_settings";
    }

    setTimeout(redirect, 3000);
</script>

This will redirect you to from the error page to the user_settings page automatically after 3 seconds.

Hope this helps!