Adam
Adam

Reputation: 3128

Passing 4 digits to view

Why this is not working:

(r'^something/(?P<id1>\d+)/(?P<id2>\d+)/(?:(?P<id3>\d+)/)(?:(?P<id4>\d+)/)?$', 'something'),

What I am trying to achieve is having the first digits required and the third and fourth optional. So the user may pass 2, 3 or 4 params to the view which is defined as follow:

def compare(request, id1, id2, id3=None, id4=None):

My current code work when passing 3 or 4 args, not 2.

What's wrong?

Upvotes: 0

Views: 52

Answers (1)

Pavel Anossov
Pavel Anossov

Reputation: 62928

The third digit-group is mandatory in your regex.

^something/(?P<id1>\d+)/(?P<id2>\d+)/(?:(?P<id3>\d+)/)?(?:(?P<id4>\d+)/)?$

Also, as written, slashes after third and fourth groups are mandatory:

In [4]: p = re.compile(r'^something/(?P<id1>\d+)/(?P<id2>\d+)/(?:(?P<id3>\d+)/)?(?:(?P<id4>\d+)/)?$')

In [5]: p.match('something/1/2/3/4/').groups()
Out[5]: ('1', '2', '3', '4')

In [6]: p.match('something/1/2/3/4').groups()
Out[6]: ('1', '2', '3', None)

In [7]: p.match('something/1/2/3/').groups()
Out[7]: ('1', '2', '3', None)

In [8]: p.match('something/1/2/3').groups()
Out[8]: ('1', '2', None, None)

In [9]: p.match('something/1/2/').groups()
Out[9]: ('1', '2', None, None)

You might want to move the third to the fourth group and make the fourth one optional:

In [12]: p = re.compile(r'^something/(?P<id1>\d+)/(?P<id2>\d+)/(?:(?P<id3>\d+))?(?:/(?P<id4>\d+)/?)?$')

In [13]: import re
KeyboardInterrupt

In [13]: p.match('something/1/2/3/4').groups()
Out[13]: ('1', '2', '3', '4')

In [14]: p.match('something/1/2/3/').groups()
Out[14]: ('1', '2', '3', None)

In [15]: p.match('something/1/2/3').groups()
Out[15]: ('1', '2', '3', None)

In [16]: p.match('something/1/2/').groups()
Out[16]: ('1', '2', None, None)

Upvotes: 4

Related Questions