Redirect with parameters

Hi,

I’m new to Django so I will try to explain my problem as clearly as possible.

I would like to have a HTML page which allows me to select an option and then I click a button to run a python function with this option (parameter), then the result of the function is displayed in the same page.

So I have a HTML page named mypage.html containing a form with a select and a button, the form posts:
<form method="post" action="/abc">{% csrf_token %}
Where abc is my application and also the actual page.
there is also a way to display the result if exists:

{% if result %}
{{result}}
{% endif %}

In my urls I have:
path('abc', views.abc, name = 'abc'),

In my views I have:

def abc(request):
    data_res = 0
    if request.method == "POST":
        stop = request.POST["stop"]
        data_res = rnd.randrange(stop)


    return render(request, 'abc/mypage.html', {'result':data_res})

It works fine, but my problem is that, if I update the page, my function is run again, I would like to avoid this and to run my function ONLY if I submit the form.

So I tried something like:

if request.method == "POST":
        stop = request.POST["stop"]
        data_res = rnd.randrange(stop)
        return redirect('abc', {'result':data_res})

But I receive the error:
Reverse for ‘abc’ with arguments ‘my result’ not found. 1 pattern(s)

How can I solve this problem ?

Thank you very much for your support.

Welcome @JulienMell !

First, when posting code here, please post the actual code - do not try to post a summary, edited or otherwise-modified version. More often than not, we end up trying to debug an example that does not match the actual code.

In this case you have syntax errors in both code fragments you’re showing.

Also, when you’re getting an error message, please post the complete error message with the traceback from the server console. (Do not post the error summaries as a screenshot of the browser window.)

Side note: If the view that created this page is the same page you’re posting to, you don’t need to use the action attribute in your <form element.

What function are you talking about?

Hi Ken,

Thank you for your fast reply.

We can assume without loss of generality that the function is like a function generating random number, and the parameter I want to select is the stop parameter, I have updated my initial post accordingly.

So my goal is that the randomnumber is not re-generated when we refresh the page, but only on clicking on the button.

You can find here after the traceback, in my real code the epr app is the abc in my first post.
Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/epr

Django Version: 5.1.3
Python Version: 3.13.0
Installed Applications:
[‘authentication.apps.AuthenticationConfig’,
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘userprofile’,
‘quantumapplications’,
‘backends’,
‘epr’]
Installed Middleware:
[‘django.middleware.security.SecurityMiddleware’,
‘django.contrib.sessions.middleware.SessionMiddleware’,
‘django.middleware.common.CommonMiddleware’,
‘django.middleware.csrf.CsrfViewMiddleware’,
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
‘django.contrib.messages.middleware.MessageMiddleware’,
‘django.middleware.clickjacking.XFrameOptionsMiddleware’]

Traceback (most recent call last):
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\core\handlers\exception.py”, line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\core\handlers\base.py”, line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\contrib\auth\decorators.py”, line 60, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\Documents\Perso\Projects\myproject\myproject\epr\views.py”, line 41, in epr
return redirect(‘epr’, {‘backends’: backends, ‘result’:data_res})
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\shortcuts.py”, line 49, in redirect
return redirect_class(resolve_url(to, *args, **kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\shortcuts.py”, line 180, in resolve_url
return reverse(to, args=args, kwargs=kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\urls\base.py”, line 88, in reverse
return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\julien\AppData\Local\anaconda3\envs\myproject\Lib\site-packages\django\urls\resolvers.py”, line 831, in _reverse_with_prefix
raise NoReverseMatch(msg)
^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: NoReverseMatch at /epr
Exception Value: Reverse for ‘epr’ with arguments ‘({‘backends’: <QuerySet [<GateBasedBackend: Simulator>, <GateBasedBackend: QPU>]>, ‘result’: {‘11’: 478, ‘00’: 522}},)’ not found. 1 pattern(s) tried: [‘epr\Z’]

You’re still not providing complete and accurate information.

We are going to be unable to assist you until the code you provide matches the error messages being generated.

Hi Ken,

Here is the content of relevent part of my files:

index.html:

<form method="post" action="/epr">{% csrf_token %}
<label for="backend">Select a backend:</label>
<select name="backend" id="backend">
	{% for backend in backends %}
	<option value="{{ backend.name }}">{{ backend.name }}</option>
	{% endfor %}
  </select>
<button type="submit">Submit</button>
</form>
{% if result %}
{{result}}
{% endif %}

views.py:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from backends.models import GateBasedBackend

from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

def home(request):
    return render(request,"index.html")

@login_required
def epr(request):
    user_grp_list = list(request.user.groups.values_list('name',flat = True))
    backends = GateBasedBackend.objects.filter(level__in=user_grp_list)

    data_res = 0
    if request.method == "POST":
        backend = request.POST["backend"]
        if backend=="Simulator":
            qc = QuantumCircuit(2)
            qc.h(0)
            qc.cx(0, 1)
            qc.measure_all()
            result = StatevectorSampler().run([qc], shots=1000).result()
            data_res = result[0].data.meas.get_counts()
        return redirect('epr', {'backends': backends, 'result':data_res})
    return render(request, 'epr/index.html', {'backends': backends, 'result':data_res})

urls.py:

from django.urls import path, include
from . import views
urlpatterns = [
    path('epr', views.epr, name = 'epr'),
]

So I want to avoid re-posting when we refresh the page, but only when clicking on the button.

You are passing two keyword parameters to the url named epr:

But your epr url doesn’t accept parameters.

This mismatch is the direct cause of the error you posted above.

You should remove those parameters from the redirect function.

Can you clarify what you mean by this?

My initial code is without the line:
return redirect('epr', {'backends': backends, 'result':data_res})
So here is what appends: when I load the epr/ page for the first time, I select an option, I click on submit, a POST request is sent, my function is run, the result is returned thanx to:
return render(request, 'epr/index.html', {'backends': backends, 'result':data_res})

That’s nice, but now if I refresh the page by hitting F5 for example, an other POST request is sent, my function is run once again and I have a new result, I don’t want that, I want the page to display the previous result when refreshing, but run my function only if I click the button once again.
So I tried to avoid that by using redirect instead of render, but it generates the error.
[edit: I tried redirect because I read on the forum that it was the good practice to redirect after a POST]

So my question is, how to avoid running my function again when rfreshing but displaying the current result instead ?

I hope I’m clear.

You are now, thanks.

Unfortunately, what you’re trying to do isn’t possible in HTTP. The http protocol is stateless. Your view doesn’t retain data between requests. And refreshing the rendering of the same page in the post handling causing a repeat of the post is how browsers work by design - that’s not something you can change from the server.

Since the views don’t maintain state, when you redirect, there’s nothing from the previous request to use.

You either need to either pass the data through to the next request, which means either as url parameters or as query parameters, or cache it (session, database, etc) and pass some key to indicate that in the new request. (Passing the data through the url or query variables is easier if the amount of data is small. Persisting the data on the server is require if the data is large.)

In either case, you’re going to need to define a new url for these “augmented” requests that can accept the parameters. You’ll also either need to create a new view to handle those parameters, or modify your existing view to check for their existance and take appropriate action.

All understood. Thank you for your help.