How to capture multiple arguments using a single RegEx in my Django urls.py?
I've got an application that allows you to filter data via 3 fields. I'm trying to write a RegEx in my urls.py that can capture multiple combinations without having to write-out each possible combination it it's own URL.
Here's my urls.py:
#urls.py
urlpatterns = patterns('',
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
(r'(?P<key>\w*?)=(?P<value>\w*?)&|$', views.scriptFilter),
I tested the above RegEx at pythonregex.com and it appears to capture as many key/value pairs as I can throw at it. However, when I test try it in my app, Django only returns a queryset based on the first pair, and ignores the other pairs.
For example, if I enter this: http://MYSITE/feature=1&session=1&
Django returns the data based on feature=1 only and ignores session=1.
Here's my views.py:
#views.py
def scriptFilter(request, key, value):
if key == 'session':
sessionID = value
qs = models.Script.objects.filte开发者_如何学Pythonr(session=sessionID)
elif key == 'product':
productID = value
qs = models.Script.objects.filter(product=productID)
elif key == 'feature':
featureID = value
scriptFeature = models.Feature.objects.get(pk=featureID)
qs = models.Script.objects.filter(feature=scriptFeature)
else:
qs = models.Script.objects.all()
caseTotal = qs.aggregate(Sum('caseCount'))
scriptTotal = qs.aggregate(Count('subScriptName'))
featureTotal = qs.aggregate(Count('feature'))
return render_to_response('scripts.html', locals())
I'm new to Python & Django so please be gentle :) Any help would be really appreciated.
These may be valid URLs (not entirely certain) but they're certainly not recommended.
If you want to allow parameters sent into your application using key-value pairs (as you are doing here), I'd suggest just using query parameters. Here's a way to implement that in your view:
def scriptFilter(request, session=None, product=None, feature=None):
session = request.REQUEST.get('session',session)
product = request.REQUEST.get('product',session)
feature = request.REQUEST.get('feature',session)
if session
qs = models.Script.objects.filter(session=session)
elif product:
qs = models.Script.objects.filter(product=product)
elif feature:
qs = models.Script.objects.filter(feature=feature)
else:
qs = models.Script.objects.all()
caseTotal = qs.aggregate(Sum('caseCount'))
scriptTotal = qs.aggregate(Count('subScriptName'))
featureTotal = qs.aggregate(Count('feature'))
return render_to_response('scripts.html', locals())
You'd then call the URLs as
- http://example.com/myapp?session=X
- http://example.com/myapp?product=X
- http://example.com/myapp?session=X&feature=Y
etc.
Note that I assume when you say that pythonregex captured all the groups, that's probably because you were looking at the .findall()
response. I'm not sure of the exact mechanics of Django's url dispatcher, but even if you just think about it logically, how could it assign more than one value to key
and value
? Your scriptFilter
function does not even handle multiple values being sent in. You really want it to read:
def scriptFilter(request, session=None, product=None, feature=None):
session = request.REQUEST.get('session',session)
product = request.REQUEST.get('product',session)
feature = request.REQUEST.get('feature',session)
qs = models.Script.objects.all()
if session
qs = qs.filter(session=session)
if product:
qs = qs.filter(product=product)
if feature:
qs = qs.filter(feature=feature)
caseTotal = qs.aggregate(Sum('caseCount'))
scriptTotal = qs.aggregate(Count('subScriptName'))
featureTotal = qs.aggregate(Count('feature'))
return render_to_response('scripts.html', locals())
Finally, I'm guessing you should rewrite these lines as well: caseTotal = qs.aggregate(Sum('caseCount')) scriptTotal = qs.aggregate(Count('subScriptName')) featureTotal = qs.aggregate(Count('feature'))
The aggregate
function creates a QuerySet with the aggregated values. You may as well group these into one queryset:
script_totals = qs.aggregate(Sum('casecount'), Count('subscriptname'), Count('feature'))
In the template, you'd access these values as:
{{ script_totals.casecount__sum }}
{{ script_totals.subscriptname__count }}
{{ script_totals.feature__count }}
Which is a bit cleaner than
{{ caseTotal.casecount__sum }}
{{ scriptTotal.subscriptname__count }}
{{ featureTotal.feature__count }}
精彩评论