DJANGO - Redirect to different page from POST with data

24,080

Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.

def get_name(request):

    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        ...
    else:
        form = NameForm()
    template = loader.get_template("app/name.html")
    context = {'form': form}
    return HttpResponse(template.render(context, request))

If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.

    if form.is_valid():
        return redirect('thanks')

Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.

This works because you have name='thanks' in your url pattern.

You can simplify your views by using the render shortcut. Instead of

template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))

you can simply do:

return render(request, "app/name.html", context)

Remember to add the imports for the shortcuts:

from django.shortcuts import redirect, render
Share:
24,080
Jeeves
Author by

Jeeves

I am a program. I am without form.

Updated on May 10, 2020

Comments

  • Jeeves
    Jeeves almost 4 years

    I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.

    My directory structure is as follows:

    appName/
           app/
              forms.py
              urls.py
              views.py
              templates/
                   app/
                     goodbye.html
                     name.html
                     library.html
                     thanks.html
           appName/
               settings.py
               urls.py
    

    My app/urls.py is as follows:

    from django.conf.urls import url
    from . import views
    
    app_name = 'app'
    
    urlpatterns = [
            url(r'^$', views.index2, name = 'index'),
            url(r'^hello/$', views.hello, name = 'hello'),
            url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
            #url(r'^library$', views.library, name = 'library'),
            url(r'^library/$', views.library, name = 'library'),
            url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
            url(r'^getname/$', views.get_name, name = 'get_name'),
            url(r'^your-name/$',views.get_name, name='get_name'),
            url(r'^thanks/$',views.say_thanks,name='thanks'),
            #url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
            ]
    

    My forms.py is :

    from django import forms

    class NameForm(forms.Form):
        your_name = forms.CharField(label = 'Your name', max_length=100)
    

    My app/views.py is:

    from django.http import HttpResponse
    from django.template import loader
    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    
    #forms
    from .forms import NameForm
    
    # Create your views here.
    def index2(request):
        return HttpResponse("hello world")
    
    def hello(request):
        text = """<h1>Welcome to my app! </h1>"""
        return HttpResponse(text)
    
    def goodbye(request):
        template = loader.get_template("app/goodbye.html")
        context = {
            'output' : 'This is output from goodby views.py request handler'
            }
    
        return HttpResponse(template.render(context,request))
    
    def library(request):
        template = loader.get_template("app/library.html")
        context = {
            'output' : 'Welcome to the libary!!'
            }
        return HttpResponse(template.render(context, request))
    
    def book(request, book_id):
        return HttpResponse("You're looking at book %s. " % book_id)
    
    def get_name(request):
    
        # if this is a POST request we need to process the form data
        if request.method == 'POST':
            # create a form instance and populate it with data from the request:
            form = NameForm(request.POST)
            # check whether it's valid:
            if form.is_valid():
                #process the data in form.cleaned_data as required
                locationGo = "/thanks/"
                template = loader.get_template("app/thanks.html")
    
                return HttpResponse(template.render({'name':'name'},request))
        else:
                form = NameForm()
                template = loader.get_template("app/name.html")
                context = {'form': form}
                return HttpResponse(template.render(context, request))
    
    def say_thanks(request):
        template = loader.get_template("app/thanks.html")
        return HttpResponse(template.render({'name': 'name'},request))
    

    My templates include:

    name.html :

    <form action = "/getname/" method = "post">
        {% csrf_token %}
        {{ form }}
        <input type = "submit" value = "Submit" />
    </form>
    

    goodbye.html

    <h1>Goodbye to Template Romance</h1>
    
    <a href="{% url 'app:index' %}">Go Back</a>
    

    thanks.html

    Thanks {{name}}!
    

    What I would like is for:

    1. A user to visit to : website.com/getname/ to show the name.html file (which it does)

    2. If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.

    3. If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)

    Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).

    Any suggestions would be a big help!