{% url admin:index %} generating wrong urls

169 views
Skip to first unread message

Chris Withers

unread,
Dec 24, 2009, 2:56:09 PM12/24/09
to django...@googlegroups.com
Hi All,

My django site is served up with the following in Apache's config:

WSGIScriptAlias /studio /django/studio/bin/django.wsgi

My urls.py looks like:

urlpatterns += patterns(
'django.contrib',
(r'^admin/', include(admin.site.urls)),
(r'^accounts/login/$', 'auth.views.login'),
(r'^accounts/logout/$', 'auth.views.logout'),
)

...and yet:

[<a href="{% url admin:index %}">admin</a>]

...generates a link to /admin rather than /studio/admin.
Bizarrely, the urls within the admin interface itself are fine.

I'm using:

Python 2.5.2-3
Django 1.1.1
mod_wsgi 2.5-1~lenny1
apache2 2.2.9-10+lenny6

Can anyone tell me what I'm doing wrong?

cheers,

Chris

--
Simplistix - Content Management, Batch Processing & Python Consulting
- http://www.simplistix.co.uk

rebus_

unread,
Dec 25, 2009, 4:29:14 AM12/25/09
to django...@googlegroups.com
2009/12/24 Chris Withers <ch...@simplistix.co.uk>:
> --
>

Seems to me you are missing namespace definitions in your URL for that to work.

http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces

Karen Tracey

unread,
Dec 25, 2009, 6:44:28 PM12/25/09
to django...@googlegroups.com
On Thu, Dec 24, 2009 at 2:56 PM, Chris Withers <ch...@simplistix.co.uk> wrote:
Hi All,

My django site is served up with the following in Apache's config:

WSGIScriptAlias /studio /django/studio/bin/django.wsgi

My urls.py looks like:

urlpatterns += patterns(
    'django.contrib',
    (r'^admin/', include(admin.site.urls)),
    (r'^accounts/login/$', 'auth.views.login'),
    (r'^accounts/logout/$', 'auth.views.logout'),
    )

...and yet:

[<a href="{% url admin:index %}">admin</a>]

...generates a link to /admin rather than /studio/admin.
Bizarrely, the urls within the admin interface itself are fine.

I'm using:

Python 2.5.2-3
Django 1.1.1
mod_wsgi  2.5-1~lenny1
apache2 2.2.9-10+lenny6

Can anyone tell me what I'm doing wrong?


No idea.  I can't recreate by copy & pasting you urlpatterns.  Tried on Django 1.1.1 and current trunk.  I've got mod_wsgi 2.3 instead of 2.5 but I doubt that makes a difference for this -- everything else the same level as yours. Can you recreate with a bare-bones setup?

Karen

Chris Withers

unread,
Dec 26, 2009, 3:28:24 AM12/26/09
to django...@googlegroups.com
Karen Tracey wrote:
> Can anyone tell me what I'm doing wrong?
>
>
> No idea. I can't recreate by copy & pasting you urlpatterns. Tried on
> Django 1.1.1 and current trunk. I've got mod_wsgi 2.3 instead of 2.5
> but I doubt that makes a difference for this -- everything else the same
> level as yours. Can you recreate with a bare-bones setup?

Short of firing up a blank VM, I'm not sure how much more bare bones I
can get :-S

Not sure if it helps but:

- I'm running the whole project out of a buildout using djangorecipe
0.20 (although I did trace through the django.wsgi file and all the work
is still done by django.core.handlers.wsgi.WSGIHandler

- A workaround which solves the problem for me is to precede the
WSGIScriptAlias in the apache config with:

RewriteRule ^/studio$ /studio/ [R]

cheers,

Chris

PS: I never got my original message mailed back to me from the list, was
I stuck in the google groups moderation queue?

Graham Dumpleton

unread,
Dec 26, 2009, 4:26:59 AM12/26/09
to Django users

On Dec 26, 7:28 pm, Chris Withers <ch...@simplistix.co.uk> wrote:
> Karen Tracey wrote:
> >     Can anyone tell me what I'm doing wrong?
>
> > No idea.  I can't recreate by copy & pasting you urlpatterns.  Tried on
> > Django 1.1.1 and current trunk.  I've got mod_wsgi 2.3 instead of 2.5
> > but I doubt that makes a difference for this -- everything else the same
> > level as yours. Can you recreate with a bare-bones setup?
>
> Short of firing up a blank VM, I'm not sure how much more bare bones I
> can get :-S

As I told you when you tried to use private email to get me to help on
this, try using a simple test program when validating things and not
use a high level framework. See:

http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Displaying_Request_Environment

for a simple test program that echos back WSGI request environment.

The key thing you want to be looking at is the value of SCRIPT_NAME as
is passed in the WSGI environment. If it is /studio then mod_wsgi is
doing exactly what it is meant to and Django or your configuration of
Django is causing a problem.

> - I'm running the whole project out of a buildout using djangorecipe
> 0.20 (although I did trace through the django.wsgi file and all the work
> is still done by django.core.handlers.wsgi.WSGIHandler

Yes, but what exactly does the WSGI script file contain in regard to
the 'application' object. For Django it normally would be:

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

If that buildout recipe is doing anything else fancy in it and is
modifying the WSGI environment, especially the values of SCRIPT_NAME
and PATH_INFO, then it could be stuffing it all up.

> - A workaround which solves the problem for me is to precede the
> WSGIScriptAlias in the apache config with:
>
> RewriteRule ^/studio$ /studio/ [R]

Which definitely shouldn't be required unless the WSGI script file is
screwing things up, or you perhaps some other rewrite rule, or
conflicting configuration in Apache configuration and this rule is
short circuiting things so the other rule/configuration directives
don't get a chance to affect things.

What you should do is disable that rewrite rule and then enable Apache
rewrite rule logging to see what other rewrites are occurring in case
there is something else which is playing with the URL which shouldn't
be.

The best first step though on working this out though is that test
program you were pointed to in the documentation. Use it instead of
Django and then post examples of the WSGI environment for requests:

/studio
/studio/
/studio/subdir

Ensuring you don't have that rewrite rule in place.

Also post all mod_wsgi relevant bits of your Apache configuration so
can see what else you have in there. If you had for example other
configuration, especially WSGIScriptAliasMatch or ScriptAliasMatch
directives that also match, then they could be getting applied and
causing issues if the way you used those directives is wrong, as they
can have side affects of modifying SCRIPT_NAME and PATH_INFO and the
relationships between them.

Graham

Chris Withers

unread,
Dec 26, 2009, 7:18:52 AM12/26/09
to django...@googlegroups.com
Graham Dumpleton wrote:
>
> As I told you when you tried to use private email to get me to help on
> this,

Apologies for that, I was actually trying to use Google's web UI to
reply to that thread in context. Their UI obvious sucks more than I
realised as it just sent a private mail to you :-(

>> - I'm running the whole project out of a buildout using djangorecipe
>> 0.20 (although I did trace through the django.wsgi file and all the work
>> is still done by django.core.handlers.wsgi.WSGIHandler
>
> Yes, but what exactly does the WSGI script file contain in regard to
> the 'application' object. For Django it normally would be:
>
> import django.core.handlers.wsgi
> application = django.core.handlers.wsgi.WSGIHandler()

Yup, djangorecipe's script sets application to an instance of
django.core.handlers.wsgi.WSGIHandler(), not a subclass and with no
apparent buggering around with the environment.

> If that buildout recipe is doing anything else fancy in it and is
> modifying the WSGI environment, especially the values of SCRIPT_NAME
> and PATH_INFO, then it could be stuffing it all up.

Nope, can't see any evidence of this...

> What you should do is disable that rewrite rule and then enable Apache
> rewrite rule logging to see what other rewrites are occurring in case
> there is something else which is playing with the URL which shouldn't
> be.

Once the controversial rewrite rule is disabled and I have rewrite
logging enabled, I get straight pass through when I visit any of:

/studio
/studio/
/studio/subdir

> The best first step though on working this out though is that test
> program you were pointed to in the documentation. Use it instead of
> Django and then post examples of the WSGI environment for requests:
>
> /studio
> /studio/
> /studio/subdir
>
> Ensuring you don't have that rewrite rule in place.

Okay, so I put the debugging app you linked to in test.py and now have:

WSGIScriptAlias /studio /django/studio/bin/django.wsgi
WSGIScriptAlias /test /django/test.py

I also added a <pre>{{request}}</pre> to the base.html of the django
app. Here's the output of the request's SCRIPT_NAME for various urls:

/studio - u''
/studio/ - u'/studio'
/test - '/test'
/test/ - '/test/'


> Also post all mod_wsgi relevant bits of your Apache configuration so
> can see what else you have in there. If you had for example other
> configuration, especially WSGIScriptAliasMatch or ScriptAliasMatch
> directives that also match, then they could be getting applied and
> causing issues if the way you used those directives is wrong, as they
> can have side affects of modifying SCRIPT_NAME and PATH_INFO and the
> relationships between them.

Other than the above two WSGIScriptAlias directives, there are no
mod_wsgi directives or ScriptAlias*'s...

How can I step through execution from the django.wsgi file and see where
I get to? I'm guessing putting an "import pdb; pdb.set_trace()" in the
django.wsgi file won't do what I want?

cheers,

Chris

Graham Dumpleton

unread,
Dec 26, 2009, 3:12:57 PM12/26/09
to Django users

Hmmm, that would suggest that it is Django that is changing it for
some reason.

> > Also post all mod_wsgi relevant bits of your Apache configuration so
> > can see what else you have in there. If you had for example other
> > configuration, especially WSGIScriptAliasMatch or ScriptAliasMatch
> > directives that also match, then they could be getting applied and
> > causing issues if the way you used those directives is wrong, as they
> > can have side affects of modifying SCRIPT_NAME and PATH_INFO and the
> > relationships between them.
>
> Other than the above two WSGIScriptAlias directives, there are no
> mod_wsgi directives or ScriptAlias*'s...
>
> How can I step through execution from the django.wsgi file and see where
> I get to? I'm guessing putting an "import pdb; pdb.set_trace()" in the
> django.wsgi file won't do what I want?

Sort of, but you have to run Apache in single process mode. See
further down in same document on debugging.

http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Python_Interactive_Debugger

Graham

Chris Withers

unread,
Dec 26, 2009, 5:32:34 PM12/26/09
to django...@googlegroups.com
Graham Dumpleton wrote:
>
>> How can I step through execution from the django.wsgi file and see where
>> I get to? I'm guessing putting an "import pdb; pdb.set_trace()" in the
>> django.wsgi file won't do what I want?
>
> Sort of, but you have to run Apache in single process mode. See
> further down in same document on debugging.
>
> http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Python_Interactive_Debugger

If anyone can tell me how to do "httpd -X" on a debian or ubuntu host
I'd be very grateful...

Karen Tracey

unread,
Dec 26, 2009, 5:38:48 PM12/26/09
to django...@googlegroups.com
On Sat, Dec 26, 2009 at 5:32 PM, Chris Withers <ch...@simplistix.co.uk> wrote:

If anyone can tell me how to do "httpd -X" on a debian or ubuntu host
I'd be very grateful...


/usr/sbin/apache2 -X

Karen

Chris Withers

unread,
Dec 26, 2009, 5:39:45 PM12/26/09
to django...@googlegroups.com
Chris Withers wrote:
> Graham Dumpleton wrote:
>>> How can I step through execution from the django.wsgi file and see where
>>> I get to? I'm guessing putting an "import pdb; pdb.set_trace()" in the
>>> django.wsgi file won't do what I want?
>> Sort of, but you have to run Apache in single process mode. See
>> further down in same document on debugging.
>>
>> http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Python_Interactive_Debugger
>
> If anyone can tell me how to do "httpd -X" on a debian or ubuntu host
> I'd be very grateful...

In case anyone else needs it:

apache2ctl -X

*sigh* -> why must the debian guys bugger up everything in their distros?!

Chris Withers

unread,
Dec 26, 2009, 5:59:41 PM12/26/09
to django...@googlegroups.com

For me that gave:

# /usr/sbin/apache2 -X
apache2: bad user name ${APACHE_RUN_USER}

However, as I said in my other thread, what did work for me was:

apache2ctl -X

cheers,

Chris Withers

unread,
Dec 26, 2009, 6:07:49 PM12/26/09
to django...@googlegroups.com
Graham Dumpleton wrote:
>
>> I also added a <pre>{{request}}</pre> to the base.html of the django
>> app. Here's the output of the request's SCRIPT_NAME for various urls:
>>
>> /studio - u''
>> /studio/ - u'/studio'
>> /test - '/test'
>> /test/ - '/test/'
>
> Hmmm, that would suggest that it is Django that is changing it for
> some reason.

I believe it's a bug in Django:

http://code.djangoproject.com/browser/django/tags/releases/1.1.1/django/core/handlers/base.py#L204

Sadly, still there on the branch and trunk:

http://code.djangoproject.com/browser/django/branches/releases/1.1.X/django/core/handlers/base.py#L215
http://code.djangoproject.com/browser/django/trunk/django/core/handlers/base.py#L215

The problem is when PATH_INFO is empty, as it is in the top case. Python
has no notion of positive or negative zero (;-)) so we end up returning
script_url[:0]...

Now, I'm really curious that Karen says this works for her. Karen, can
you have a look at what's different about your apache setup, as I can't
see how this would ever correctly work for the "root url without the
slash" case.

I have to admit, I can't see why the script name would ever need to be
trimmed like that. Graham, perhaps you might be able to shed some light
with your greater wsgi experience?

Karen Tracey

unread,
Dec 26, 2009, 6:09:45 PM12/26/09
to django...@googlegroups.com
On Sat, Dec 26, 2009 at 5:59 PM, Chris Withers <ch...@simplistix.co.uk> wrote:
Karen Tracey wrote:
> On Sat, Dec 26, 2009 at 5:32 PM, Chris Withers <ch...@simplistix.co.uk
> <mailto:ch...@simplistix.co.uk>> wrote:
>
>
>     If anyone can tell me how to do "httpd -X" on a debian or ubuntu host
>     I'd be very grateful...
>
>
> /usr/sbin/apache2 -X

For me that gave:

# /usr/sbin/apache2 -X
apache2: bad user name ${APACHE_RUN_USER}

Oh right.  I had previously run source /etc/apache2/envvars to get the environment vars exported.
 

However, as I said in my other thread, what did work for me was:

apache2ctl -X


I forgot about that one.  It's a front-end to the other that does the environment variable setup automatically.

Karen

Karen Tracey

unread,
Dec 26, 2009, 6:43:06 PM12/26/09
to django...@googlegroups.com
On Sat, Dec 26, 2009 at 6:07 PM, Chris Withers <ch...@simplistix.co.uk> wrote:
Graham Dumpleton wrote:
>
>> I also added a <pre>{{request}}</pre> to the base.html of the django
>> app. Here's the output of the request's SCRIPT_NAME for various urls:
>>
>> /studio   - u''
>> /studio/  - u'/studio'
>> /test     - '/test'
>> /test/    - '/test/'
>
> Hmmm, that would suggest that it is Django that is changing it for
> some reason.

I believe it's a bug in Django:

http://code.djangoproject.com/browser/django/tags/releases/1.1.1/django/core/handlers/base.py#L204


Inline is easier to see:

    script_url = environ.get('SCRIPT_URL', u'')
    if not script_url:
        script_url = environ.get('REDIRECT_URL', u'')
    if script_url:
        return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
    return force_unicode(environ.get('SCRIPT_NAME', u''))

Line 204 is the one that returns a modified script_url based on what's in PATH_INFO.

 [snip]
The problem is when PATH_INFO is empty, as it is in the top case. Python
has no notion of positive or negative zero (;-)) so we end up returning
script_url[:0]...

Now, I'm really curious that Karen says this works for her. Karen, can
you have a look at what's different about your apache setup, as I can't
see how this would ever correctly work for the "root url without the
slash" case.

In my case, environ.get('SCRIPT_URL', u'') and environ.get('REDIRECT_URL', u'') both return empty.  So I don't get to line 204, I go to line 205, which returns the correct value. I don't know what's different about my Apache setup to result in that difference, this is a pretty bare-bones virtual host I have set up for testing. 
 
Since rewrites were mentioned earlier perhaps it's significant that this Apache setup doesn't have mod_rewrite enabled.

Karen

Chris Withers

unread,
Dec 26, 2009, 6:54:44 PM12/26/09
to django...@googlegroups.com
Karen Tracey wrote:
> In my case, environ.get('SCRIPT_URL', u'') and
> environ.get('REDIRECT_URL', u'') both return empty.

I wonder what SCRIPT_URL is and why it's empty for you but not for me?

I wonder if SCRIPT_URL having a value is something that came along with
a later version of mod_wsgi? Could you trying using the debian-packaged
mod_wsgi (whih is version 2.5.x) and see if that changes the behaviour
you observe?

> Since rewrites were mentioned earlier perhaps it's significant that this
> Apache setup doesn't have mod_rewrite enabled.

I don't think so, I've checked with the rewrite engine's logging and all
the urls in question are being passed straight through.

Karen Tracey

unread,
Dec 26, 2009, 7:27:47 PM12/26/09
to django...@googlegroups.com
On Sat, Dec 26, 2009 at 6:54 PM, Chris Withers <ch...@simplistix.co.uk> wrote:
Karen Tracey wrote:
> In my case, environ.get('SCRIPT_URL', u'') and
> environ.get('REDIRECT_URL', u'') both return empty.

I wonder what SCRIPT_URL is and why it's empty for you but not for me?


It's set by mod_rewrite:

http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

Enabling it and turning it on for this virtual host I see the behavior you describe, when I access the root page without a trailing slash.  With a trailing slash things are fine.

There is at least one bug open on empty PATH_INFO handling:

http://code.djangoproject.com/ticket/9435

though it doesn't sound like it's focused on exactly the same issue, and fixing this one for the special case of empty PATH_INFO may be easier than the overall problem that is the concern of that ticket.  But I don't have time at the moment to really look at it closely, nor to check if there's another open ticket that might match this one more closely.

Karen

Chris Withers

unread,
Dec 29, 2009, 6:31:31 PM12/29/09
to django...@googlegroups.com
Karen Tracey wrote:
> There is at least one bug open on empty PATH_INFO handling:
>
> http://code.djangoproject.com/ticket/9435
>
> though it doesn't sound like it's focused on exactly the same issue,

No, I had as thorough a look as I could and could find no issue which
directly covered this issue so submitted a new one:

http://code.djangoproject.com/ticket/12464

Sadly, Trac ate the indentation :-(

cheers,

davathar

unread,
Jan 3, 2010, 4:49:45 PM1/3/10
to Django users
This one has bitten me too. It also manifests when using the
'reverse' function like so:

return HttpResponseRedirect(reverse('admin_url'))

Instead of redirecting to /studio/admin/ it redirects to /admin/

So, while /studio/admin/ resolves well, reversing the path doesn't
yield the reverse.

I'm using Django 1.1.1 and mod_wsgi 2.5

Unfortunately adding the rewrite rule mentioned as a work around
hasn't worked for me.

-Shane

Chris Withers

unread,
Jan 12, 2010, 1:22:11 PM1/12/10
to django...@googlegroups.com
davathar wrote:
> Unfortunately adding the rewrite rule mentioned as a work around
> hasn't worked for me.

Please post the relevant section of your Apache config (including your
wsgi *and* rewrite lines), there's no reason the rewrite rule workaround
shouldn't work for you...

Reply all
Reply to author
Forward
0 new messages