okay, this is weird. If a user double-clicks the form submit button, even tho POST should redirect, they still get 403 FORBIDDEN with csrf failed message.
I think this is like a web developer question, is this some latency issue with my browser, network or web server? I use Apache-2 httpd with mod-wsgi daemon on AWS Linux instance behind load balancing proxy server.
Does anyone know what is happening here? I've thought about trying DEBUG true, but I didn't want to go down a rabbit hole just yet.
thanks for any help!
my form has a csrf token (on 11th line down below, sorry if this is toooo much ... fyi: using bootstrap-3 css/js elements)
<!-- login form -->
<div class="container-fluid" style="margin-top: 30px" id="login-form-container">
<div class="row-fluid">
<div class="well" style="width: 560px; margin-left: auto; margin-right: auto">
<div class="row-fluid">
<h3 style="margin: 0 0 20px;">BLAH BLAH Registration</h3>
<p style="padding-bottom: 20px">Please enter your information below to request access to BLAH:</p>
</div>
<div class="row-fluid">
<form class="form-horizontal" action="{% url 'newuser_register' %}" method="post" role="form">
{% csrf_token %}
<!-- pass next parameter as hidden form value -->
<input type="hidden" name="next" value="{{ next }}" />
<input type="hidden" name="username" value="{{ user }}" />
<div class="form-group">
{{ form.first_name.errors }}
<label for="{{ form.first_name.id_for_label }}" class="col-sm-4 control-label">{{ form.first_name.label }}:</label>
<div class="col-sm-7">{{ form.first_name }}</div>
</div>
<div class="form-group">
{{ form.last_name.errors }}
<label for="{{ form.last_name.id_for_label }}" class="col-sm-4 control-label">{{ form.last_name.label }}:</label>
<div class="col-sm-7">{{ form.last_name }}</div>
</div>
<p>Please choose a password that is at least 8 characters long:</p>
<div class="form-group">
{{ form.password1.errors }}
<label for="{{ form.password1.id_for_label }}" class="col-sm-4 control-label">{{ form.password1.label }}:</label>
<div class="col-sm-7">{{ form.password1 }}</div>
</div>
<div class="form-group">
{{ form.password2.errors }}
<label for="{{ form.password2.id_for_label }}" class="col-sm-4 control-label">{{ form.password2.label }}:</label>
<div class="col-sm-7">{{ form.password2 }}</div>
</div>
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<div class="well well-small text-error" style="border: none">{{ error }}</div>
{% endfor %}
{% endif %}
<div class="form-group">
<div class="col-sm-offset-4 col-sm-7">
<button type="submit" class="btn btn-primary">Submit</button>
<small><span style="color:#d00">*</span> - required fields</small>
</div>
</div>
</form>
</div>
<div>
{% if next %}
<p>Already a BLAH user? Please <a href="{% url 'rest_framework:login' %}?next={{ next | urlencode}}">click here</a> to login.</p>
{% else %}
<p>Already a BLAH user? Please <a href="{% url 'rest_framework:login' %}">click here</a> to login.</p>
{% endif %}
</div>
</div>
</div>
</div>
my view has redirect (on 21st line below)
def user_register(request):
"""View to register newuser."""
if request.method == 'POST':
# pop fails with This QueryDict instance is immutable
# so get next from hidden form input
next_link = request.POST.get('next', user_profile)
form = NewuserForm(request.POST)
try:
newuser = form.save()
except ValueError as err:
LOGGER.exception(err)
messages.add_message(request, messages.ERROR, _(err.message))
else:
logout(request)
login(request, newuser,
backend='django.contrib.auth.backends.ModelBackend')
msg = _('%s has been registered.' % newuser) # add success alert
messages.add_message(request, messages.SUCCESS, msg)
# always redirect after successful POST
return redirect(next_link)
else: # any other method, eg: GET
form = NewuserForm() # empty form
# get next from query string parameter
next_link = request.GET.get('next', user_profile)
return render(
request,
'registration/newuser.html',
{'form': form, 'next': next_link} # add next to context
)