views:

58

answers:

2

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&amp;session=1&amp;

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.filter(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.

+3  A: 

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

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 }}
Jordan Reiter
@jordan: any reason why this answer is marked as a community wiki?
Manoj Govindan
Easier for people to edit it if changes need to be made. If that's not what community wiki is for, sorry and feel free (whoever has this power) to change it back.
Jordan Reiter
No problems whatsoever with your choice, just curious :)
Manoj Govindan
@Jordan: it's a good answer, but by marking it as wiki you won't get any points for it. And unfortunately it's impossible to unset it one you've done so.
Daniel Roseman
I guess my main concern was there might be some errors that needed to be fixed. I suppose in the future I can always just respond to comments instead.
Jordan Reiter
@Jordan -- absolutely. And in addition, those with enough rep can edit it whether it is a wiki or not, if the mistake is really bad ;-)
Sean Vieira
@Jordon - Also, excellent answer! +1
Sean Vieira
A: 

Jordan,

Thanks for taking the time to look at & answer my question. I appreciate the tips. In case anyone else finds this page, I found the solution specifically for my RegEx question at the url below:

http://stackoverflow.com/questions/249110/django-arbitrary-number-of-unnamed-urls-py-parameters

Thanks again!

Ashton