Passing Arguments to Django Views From a Rendered Page
I've been tasked to build web-based front end to an existing MySQL database. I'm new to web development in general, decided to use Django because I'm a pretty advanced Python user. However, I'm completely stuck doing what seems like it should be a pretty common task.
The database holds information about Software Bill of Materials (SBOMs) and the pieces of software associated with each. Right now, all I want to do is have the user select an SBOM from the database, retrieve the software associated with that SBOM, and display the results. I would like the user to be able to page through the results.
I'm trying to do this by rendering a list of SBOMs in the system in HTML, with each entry having an associated button that will pass the selected parameters to the next view in line. As far as I can tell, I have things set up so
Here's how my urls.py
is set up:
urlpatterns = [
path("", views.select_bill, name="select_bill"),
path("select_software/<int:bill_num>", views.select_software, name="select_software"),
path("select_software/<int:bill_num>/<int:page>", views.select_software, name="select_software")
]
my views.py
:
from django.shortcuts import render
from django.core.paginator import Paginator
from frontend.models import SoftwareResults
RESULTS_PER_PAGE = 25
def select_bill(request):
bills = get_bills() # Function that queries the existing MySQL database and gets a list of SBOMs
return render(request, "frontend/select_bill.html", {"bills": bills})
def select_software(request, bill_num, page=1):
<snip>
And frontend/select_bill.html
:
<table>
{% for entry in bills %}
{% url 'select_software' "{{ entry.Row }}" 1 as entry_select %}
<tr><td>
<a href="{{ entry_select }}">Submit</a></td><td>{{ entry.Filename }}</td></tr>
</table>
As far as I can tell, that should generate a link with the form /select_software/<bill_num>/1, which should in turn link to my select_software view through urls.py. Problem is, the url resolves as a link back to the select_bills page, apparently completely ignoring the {% url %}
macro above.
Things I have tried:
- Putting the
{% url %}
macro directly in thehref
text. This generates an error when the page is rendered - Using a form rather than a link. When I tried to use the POST method I got the same results. With the GET method I could encode my parameters in the URL, but that fell apart when I wanted some pages to redirect to each other.
I'm at my wit's end here. How can I get Django to create the URL I need?
Putting the
{% url %}
macro directly in the href text. This generates an error when the page is rendered
This is guesswork because you have not provided the error Django helpfully made for you. :) But:
You probably should not give multiple routes the same name. Use e.g. name="select_software_with_default_page"
for the first select_software
one, so it can be distinguished from the second one. As it is, Django can't really know which route to generate.
Also note this part of the documentation:
This
{% url ... as var %}
syntax will not cause an error if the view is missing. In practice you’ll use this to link to views that are optional:
So what likely happened (I haven't tested though) is that url
fails silently, entry_select
remains blank, the generated HTML is <a href="" ...>
, which browser will link to the same URL that is being displayed.
Instead, you might want to use the more usual form:
<a href="{% url 'select_software' "{{ entry.Row }}" 1 %}">Submit</a></td><td>{{ entry.Filename }}</td></tr>
which, as you note, does generate an error when something is wrong:
Note that if the URL you’re reversing doesn’t exist, you’ll get an
NoReverseMatch
exception raised, which will cause your site to display an error page.
Errors are good: they tell you what to fix.