1

How can I pass parameters via URL as query parameters to avoid multiple and complicated url patterns?

For example, instead of making a complicated url like example.com/page/12/red/dog/japan/spot or something like that, and then a corresponding entry in urls.py that will parse that url and direct it to a view, I want to simply get a url where I can freely add or remove parameters as needed similar to the ugly way example.com/page?id=12&color=red&animal=dog&country=Japan&name=spot

Then in urls.py simply have something like

path('page/<parameter_dictionary>', views.page, name='page' parameters='parameter_dictionary)

If I have to use url patterns, how can I account for urls that have parameters that may or may not fit the pattern, such as sometimes

"/page/12/red/dog/Japan/spot" -> path('page/<int:id>/<str:color>/<str:animal>/<str:country>/<str:name>', views.page, name='page'),
"/page/12/dog/red/Japan/"-> path('page/<int:id>/<str:animal>/<str:color>/<str:country>', views.page, name='page')
"/page/dog/red/Japan/"-> path('page/<str:animal>/<str:color>/<str:country>', views.page, name='page')

I would like to just have anything sent to http://example.com/page/ go to views.page(), and then be accessible by something like

animal = request.GET['animal']
color = request.GET['color']
id = request.GET['id']

etc. so examples below would all work via one entry in urls.py

example.com/page?id=12&animal=dog&country=Japan&name=spot 
example.com/page?id=12&color=red&animal=dog&name=spot
example.com/page?id=12&country=Japan&color=red&animal=dog&name=spot 
Ivan Starostin
  • 8,798
  • 5
  • 21
  • 39
Kbeen
  • 21
  • 4

1 Answers1

0

You are looking for queryparameters and you are almost done with it. The following code is untested but should kinda work:

def page(request):
    animal = request.GET.get("animal",None) # default None if not present
    color = request.GET.get("color",None)
    return render(request,'some_html.html')
# urls.py:
path('page/', views.page, name='page')

You access the queryparameters via the passed request object request.GET. This is a dict like object. The main difference is that this object handles multi keys.

For example if you pass the these params ?a=1&a=2 to your url, it converts request.GET.getlist("a") # Returns ["1","2"] to a list. request.GET.get("a") returns the last passed value "2" as @Kbeen mentioned in comments,. Read more about QueryDict here.

Also be sure to know the difference and best practice for url parameters and queryparameters. Example Stackoverflow post

Edit: Added request.GET.getlist()

jmangold
  • 150
  • 6
  • Also worth pointing out that if you create and populate a Querydict, then it will generate a correctly encoded querystring for you to use in (say) a redirect. `querystring = querydict.urlencode()`. And of course request.GET is a populated Querydict if you want to pass a querystring from one view to the next. – nigel222 Jul 01 '22 at 09:10
  • Awesome. Thank you! I never even thought to actually just try to send it via "?a=this&b=that" because I never came across any example of that being done in my searches. I am new to Python after a fifteen year break from programming where I used Perl and PHP exclusively. I thought maybe the ugly urls had been done away with when I was gone. – Kbeen Jul 01 '22 at 17:14
  • 1
    Just an edit to the jmangold's answer "for example if you pass the these params ?a=1&a=2 to your url, it converts `request.GET.get("a") # Returns ["1","2"].`" That was just returning the last value in the list. To get the full list it should be `request.GET.getlist("a") # Returns ["1","2"]` – Kbeen Jul 02 '22 at 13:09