Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DJANGO - Redirect to different page from POST with data

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!

like image 501
Jeeves Avatar asked Mar 12 '23 15:03

Jeeves


1 Answers

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
like image 99
Alasdair Avatar answered Mar 16 '23 02:03

Alasdair