Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the urls.py regex evaluation order in django?

I was having some problems with the regex in urls.py (I am a beginner to django as well as regexes in general)

Here is my original urls.py

url(r'^name/(?P<name>\w+)/$', 'course.views.name'),
url(r'^', 'course.views.index'),

And I was trying to access it using this:

http://127.0.0.1:8000/name/blah/

My view looks like:

def index(request):
    return HttpResponse("Hello, sam. You're at the course index.")

def name(request, name):
    return HttpResponse("Hello, %s. You're at the course index." % name)

The result I was getting was that for no matter what input I gave, I would regularly get the "index" function, and not the "name" function. I thought the problem was with the first regex.

But then, I changed the the 2nd one to:

url(r'^$', 'course.views.index'),

And THIS works just the way I figured it to work!

I understand that "$" means end of line, but shouldnt the 1st regex have been evaluated first? What is the order in which these expressions are matched?

Adding a "$" to every url is not that big a deal, but I would like to understand why I am putting it there.

I am using Django1.4 and Python 2.7

like image 241
Samudra Avatar asked Jun 04 '12 08:06

Samudra


2 Answers

Read the Django document

How Django processes a request

When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute:

  1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has an attribute called urlconf (set by middleware request processing), its value will be used in place of the ROOT_URLCONF setting.
  2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list, in the format returned by the function django.conf.urls.patterns().
  3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
  4. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. The view gets passed an HttpRequest as its first argument and any values captured in the regex as remaining arguments.
  5. If no regex matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

It said 3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL. So I think this is a bug.

You should add $ in every url pattern unless Including other URLconfs

like image 86
shihongzhi Avatar answered Sep 17 '22 15:09

shihongzhi


You're right, the django doc tells:

How Django processes a request

When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute:

  1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has an attribute called urlconf (set by middleware request processing), its value will be used in place of the ROOT_URLCONF setting.
  2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list, in the format returned by the function django.conf.urls.patterns().
  3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
  4. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. The view gets passed an HttpRequest as its first argument and any values captured in the regex as remaining arguments.
  5. If no regex matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.

This is also what another SO post suggests to fix another URL evaluation issue.

like image 24
Emmanuel Avatar answered Sep 21 '22 15:09

Emmanuel