-2

I'm following a tutorial which works with Django, there is a URL pattern like this:

url(r'^lists/(.+)/$', views.list_view, name='list_view')

That's a greedy regex pattern and it will match something such as: lists/123/add_item/ with 123/add_item as matched-group. That is not what is expected. So I tried to change it to non-greedy one like this:

url(r'^lists/(.+?)/$', views.list_view, name='list_view')

But Django still resolve it to views.list_view

Could you please give me some explanation?

sForSujit
  • 987
  • 1
  • 10
  • 24
dvn0zzz
  • 337
  • 3
  • 13
  • Possible duplicate of [What do ^ and $ mean in a regular expression?](https://stackoverflow.com/questions/6908725/what-do-and-mean-in-a-regular-expression) – Wiktor Stribiżew May 11 '19 at 22:15

3 Answers3

1

You should remove the trailing $ from your regex, since that will always match the final / instead of the next.

I think the fact that Django does match the 2nd URL is due to Django not matching the URL but instead using a re.search. You can see this behaviour here: Django source

Exelian
  • 5,749
  • 1
  • 30
  • 49
  • Your answer seems explained regex part. but Django still resolve `lists/123/add_item` to `views.list_view` – dvn0zzz Aug 10 '17 at 08:05
  • I also guess that @daniel's answer is strictly the more correct one. Although I'd highly recommend browsing the django source to understand more of what happens on the inside. – Exelian Aug 10 '17 at 08:12
0

Explanation of ^lists/(.+?)/$:

  • ^ asserts position at start of the string
  • lists matches the characters lists literally (case sensitive)
  • / matches the character / literally (case sensitive)
  • 1st Capturing Group (.+?)
    • .+? matches any character (except for line terminators)
    • +? Quantifier — Matches between one and unlimited times, as few times as possible, expanding as needed (lazy)
  • / matches the character / literally (case sensitive)
  • $ means end of string

Credits: http://regex101.com

But I didn't understand what you want exactly to match your pattern

UPDATE:

Helpful link: https://docs.python.org/3/howto/regex.html#greedy-versus-non-greedy

wencakisa
  • 5,850
  • 2
  • 15
  • 36
  • Hi! with that pattern, I was expecting it will match only: lists/123/ but not lists/123/add_item/ – dvn0zzz Aug 10 '17 at 07:34
  • If you want to match a number only (probably an `id`), you can use `^lists/(?P[0-9]+)/$` – wencakisa Aug 10 '17 at 07:39
  • Yeah, agreed. that's somehow same solution from author of tutorial: ^lists/(\d+)/$. But I just wonder about my try. – dvn0zzz Aug 10 '17 at 07:41
0

You should restrict your pattern to capture only what you want. In your case, it seems to be digits, so:

url(r'^lists/(\d+)/$', views.list_view, name='list_view')
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895