In order to reflect user-selected filters in the URL, I need urlpatterns
to include an arbitrary number of optional parameters, e.g.:
/myview/filter1:option1/filter1:option2/filter2:option1/filter3:option5/
In the view I would do something like:
def myview(request):
if request.GET.get("filter1"):
for option in request.GET.get("filter1"):
# do something with option
if request.GET.get("filter2"):
for option in request.GET.get("filter2"):
# do something with option
# etc.
Each user-selected filter can (potentially, depending on the type of filter) have multiple selected options, and multiple filters can be applied at one time. See MobyGames as an example of exactly what I mean.
If that's not feasible with Django urlpatterns, alternatively the options could be separated by a delimiter, and in the view I could add e.g. request.GET.get("filter1").split(";")
.
I imagine I need regex
to achieve this, but I don't really know where to start. I read through the relevant docs, but didn't find anything that directly addresses this kind of pattern.
Edit: the answer at this question is somewhat helpful, but doesn't fully answer my question.
If I'm understanding correctly, I would need something like:
url(r'^myview/(?Pfilter1:<filter1>[a-zA-Z\/]*)/(?Pfilter2:<filter2>[0-9\/]*)/(?Pfilter3:<filter3>[0-9\/]{4}*)/$', myview)
Where each <filter#>
is optional, may be repeated an arbitrary number of times, and may have a different pattern (e.g. some with a-zA-Z
, some may include numbers, some may be years - I can figure out the needed patterns later).
The answer in Make Django accept url with infinite parameters is perfectly correct and would translate to something like the below for your case:
url(r'^myview/(?P<path>[a-zA-Z\/]*)/$', myview),
def myview(request, path):
filters = path.split('/')
filterdict = dict()
for item in filters:
try:
key, val = item.split(':'):
filterdict[key] = value
except e as Exceptiion:
.... # Handle malformed urls here.
What's going on in the above regex is that it will capture everything after "myview/" until the closing'/' in the URL. In regex the '^' character represents the start of the string so the regex says it should start with 'myview/' and '$' represents the end of the string so it means it should end with a '/'. All your filters including the slashes which separate them between the 'myview/' and the final '/' in the url path get captured into the path capturing group and then you split that into your list of filters in the function.
Ofcourse you should handle situations where the url is malformed with proper exception handling and watch out for any trickery manually input urls can do and how you handle those filters.
And as always, please remember url paths and query parameters are user supplied input so be careful with the supplied values and don't use them in unsafe ways where they directly interact without sanity checking with backend data or the host (e.g. dont run os.system() or os.popen() using the filters/values as that can cause some nasty security issues.)