I have a view with different 'stages' (as I wanted to keep the same URL without resorting to something like AJAX), which takes data from a form, does some processing, and then would save that data to the database.
Because I can't forward some data via POST, I wanted to save that data in a session.
For some reason, this is not working - at all.
I can see the data being extracted from the form, and I can forward that via POST, but attempting to save or retrieve it to a session either results in blank data, or a KeyError.
This is the view I am using (very trimmed down, but the error is reproducible)
def processpayment(request, *args, **kwargs):
if request.method == 'POST':
form = paymentDetailsForm(request.POST)
amount = request.POST.get('amount', False);
stage = request.POST.get('stage', False);
if (stage == "checkout"):
return render(request, "payment.html", {'form': form, 'amount': amount, 'stage': stage})
if (stage == "complete"):
return render(request, "payment.html", {'amount': request.session['amount'], 'stage': stage, 'name': request.session['name']})
if (amount == "custom"):
if form.is_valid():
amount = form_data.get('amount')
name = form_data.get('name')
request.session['amount'] = amount
request.session['name'] = name
request.session.modified = True
return render(request, "payment.html", {'form': form, 'stage': stage, 'amount': amount})
return render(request, "payment.html", {'amount': amount, 'stage': stage})
else:
return render(request, "payment.html")
return render(request, "payment.html")
This is the template I am using::
{% load static %}
{% load widget_tweaks %}
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css" integrity="sha512-rt/SrQ4UNIaGfDyEXZtNcyWvQeOq0QLygHluFQcSjaGB04IxWhal71tKuzP6K8eYXYB6vJV4pHkXcmFGGQ1/0w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
<body>
<div class="m-3">
{% if stage == "complete" %}
<<h2 class="mx-auto text-center mb-3">Name:<b> {{ name }}</h2>
{% elif stage == "checkout" %}
<div style="margin-left: 20%; margin-right: 20%;">
<h2 class="mx-auto text-center mb-3">Amount to be charged: ${{ amount }}</h2>
<div class="col-md-12 mx-auto d-flex justify-content-center mt-2">
<div class="container">
<div class="row ">
<div class="col-md-6 p-3">
<form id='formName' name='formName' action="{% url 'processpayment' %}" method="POST">
<input type="hidden" id="amount" name="amount" value="{{ amount }}">
<input type="hidden" id="stage" name="stage" value="complete">
<button type="submit" name="submit" class="btn btn-primary mt-3">Next</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% elif amount == "custom" %}
<form action="{% url 'processpayment' %}" method="POST">
<div class="container pt-3 pb-3">
<input type="hidden" id="stage" name="stage" value="checkout">
<div class="row">
<div class="col-md-6 mb-2">
{% render_field form.amount class+="form-control" placeholder="AMOUNT" %}
</div>
<div class="col-md-6 mb-2">
{% render_field form.name class+="form-control" placeholder="NAME" %}
</div>
</div>
<div class="row justify-content-center">
<span class="input-group-btn">
<button class="btn btn-primary mt-3" type="submit">Next</button>
</span>
</div>
</div>
</form>
{% else %}
<div class="col-md-12 mx-auto d-flex justify-content-center mt-2">
<div class="container">
<div class="row ">
<div class="col-md-12 text-center p-3">
<form id='formName' name='formName' action="{% url 'processpayment' %}" method="POST">
<input type="hidden" id="amount" name="amount" value="custom">
<button type="submit" name="submit" class="btn btn-primary">Make a payment</button>
</form>
</div>
</div>
</div>
</div>
{% endif %}
</div>
</body>
</html>
And just for completeness my forms.py:
from django import forms
from django.forms import widgets
from .models import PaymentMade
class paymentDetailsForm(forms.ModelForm):
name = forms.CharField(max_length=50)
amount = forms.IntegerField()
def __init__(self, *args, **kwargs):
super(paymentDetailsForm, self).__init__(*args, **kwargs)
self.fields['name'].required = False
self.fields['amount'].required = False
class Meta:
model = PaymentMade
fields = ('name', 'amount')
In the 'custom' stage, if I manually set data to be stored in a session, e.g.
request.session['newvar'] = "test works"
I can retrieve that data from the session without any issues at all. So it doesn't seem to be an issue with sessions as such as saving the data from a form into a session variable.
I assume I am missing something very simple, but after working on this for several hours and testing different things I cannot see what I am doing wrong.
edit: I also have the following settings enabled in my settings.py:
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 1200
SESSION_SAVE_EVERY_REQUEST = True