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:

  1. Putting the {% url %} macro directly in the href text. This generates an error when the page is rendered
  2. 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.

Вернуться на верх