3

In Django 1.9 (and Python 3.4) the default of APPEND_SLASH worked correctly, i.e. I could enter 'localhost:8000/ideatree/videos' and the trailing slash would be added.

After an upgrade to Django 1.11 (and Python 3.6), APPEND_SLASH is no longer working.

I've looked for deprecation notices but so far found nothing that seems to apply. (side question: how do you turn 'loud deprecation warnings' back on, as they were in previous versions?)

Here is my main urls.py:

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [   url(r'^(?i)ideatree/', include('ideatree.urls'),
 name='home'),
]

and the urls.py from the included app_space:

from django.conf.urls import url
from . import views

app_name = 'ideatree'
urlpatterns = [
   url(r'^$', views.index,name='index'),
   url(r'^(?i)features/$', views.features, name='features'),
   url(r'^(?i)videos/$', views.videos, name='videos')
]

Both these url.py files are unchanged except that in Django 1.9 I had

from django.conf.urls import patterns, include, url

in the main urls.py, but 'patterns' is now deprecated and throws a warning.

As before, I do not have APPEND_SLASH set in settings.py, relying on its default value of True, though I tried explicitly setting it to True with the same result.

Here's my middleware:

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Here's the error:

Page not found (404)
Request Method: GET
Request URL:    http://localhost:8000/ideatree/videos

Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^(?i)ideatree/ ^$ [name='index']
^(?i)ideatree/ ^(?i)features/$ [name='features']
^(?i)ideatree/ videos/$ [name='videos']

I also tried clearing the browser cache, and using a different browser in case the cache still didn't get cleared.

Logging to file at level DEBUG or level INFO shows nothing, an empty file (warning: my logging setup is untested).

There's got to be something I'm overlooking.

Ron
  • 357
  • 1
  • 6
  • 18
  • Does the redirect work if you remove `(?i)` from your regexes in your main and app urls? – Alasdair Sep 29 '17 at 22:49
  • It does not work with (?i) removed from the regexes in both urls. I also removed the app_name just in case. Same result. – Ron Oct 01 '17 at 01:04
  • I'm surprised that the patterns in the error message do not consistently contain `^(?i)`. Are you posting your exact code and error message? – Alasdair Oct 01 '17 at 08:05
  • Do you have `MIDDLEWARE` in your settings (added in Django 1.10)? – Alasdair Oct 01 '17 at 08:07
  • Ah, yes. I must be using Django 1.9 middleware. It works after 1) changing MIDDLEWARE_CLASSES to MIDDLEWARE, 2) importing the MiddlewareMixin per [so]https://stackoverflow.com/questions/40876355/django-1-10-new-style-middleware-equivalent-of-process-request , and 3) deleting SessionAuthenticationMiddleware since it no longer appears in Django 1.10 docs. I'll have to go through the docs to make sure the middleware functionality is still complete. @Alasdair can you post as an answer so I can accept? Many thanks, would never have found this without your help. – Ron Oct 01 '17 at 22:43

1 Answers1

6

Django introduced new middleware in Django 1.10. You should use the MIDDLEWARE setting if you are using new-style middleware, and MIDDLEWARE_CLASSES if you are using old-style middleware.

If you are using Django 1.10 or 1.11, then the old MIDDLEWARE_CLASSES setting is still supported, so Django should continue to redirect with the appended slash.

However, once you upgrade to Django 2.0, the MIDDLEWARE_CLASSES setting is ignored and you must switch over to MIDDLEWARE.

When you switch over to MIDDLEWARE, you should remove SessionAuthenticationMiddleware since it has no effect in 1.10 and 1.11, and is removed completely in Django 2.0.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • Maybe it was also an interaction between MIDDLEWARE_CLASSES and SessionAuthenticationMiddleware classes, which don't appear in Django 1.11 docs, since it didn't work until they were removed? – Ron Oct 03 '17 at 02:15
  • No, `SessionAuthenticationMiddleware` shouldn't cause any problems. In Django 1.11 it's a stub class for backwards compatibility reasons. It doesn't have any effect but you don't have to remove it from `MIDDLEWARE_CLASSES`. – Alasdair Oct 03 '17 at 06:43
  • If I don't comment out I SessionAuthenticationMiddleware I get "ImportError: Module "django.contrib.auth.middleware" does not define a "SessionAuthenticationMiddleware" attribute/class". And the middleware I'm using is the list straight out of the docs https://docs.djangoproject.com/en/1.11/topics/http/middleware/#activating-middleware. – Ron Oct 03 '17 at 14:12
  • You shouldn't get that error if you include `SessionAuthenticationMiddleware` in `MIDDLEWARE_CLASSES` - the middleware [still exists in Django 1.11](https://github.com/django/django/blob/7e3f8e05eb56cbd01f50b811c551a7a79b250ef7/django/contrib/auth/middleware.py#L27). If you do not need backwards compatibility with other versions of Django then it's a good idea to remove it. My point was that `SessionAuthenticationMiddleware` does not explain your original problem. – Alasdair Oct 03 '17 at 14:16
  • Yes, add_slash now works even without importing MiddlewareMixin to update middleware from 1.9 to 1.11 style, as long as I don't use SessionAuthenticationMiddleware. There's something else going on. I suspect something with the (?i) regex as you mentioned before. – Ron Oct 03 '17 at 14:18
  • All the middleware classes you are using come with Django. They already use `MiddlewareMixin` in Django 1.11. You only need `MiddlewareMixin` if you are writing your own middleware that you want to be compatible with `MIDDLEWARE_CLASSES` and `MIDDLEWARE`. – Alasdair Oct 03 '17 at 14:20
  • Are you sure you're running Django 1.11.X? The message *ImportError: Module "django.contrib.auth.middleware" does not define a "SessionAuthenticationMiddleware" attribute/class* is what I'd expect in Django 2.0. Could you have the 2.0 alpha installed? – Alasdair Oct 03 '17 at 14:32
  • Embarrassing but true. It was Django 2.0 alpha. Everything works as expected in Django 1.11. This is the real answer. Thanks again @Alasdair – Ron Oct 03 '17 at 15:05
  • Yes, upgrading to Django 2.0 explains the errors you saw. In Django 2.0, then the `MIDDLEWARE_CLASSES` setting will be ignored, `MIDDLEWARE` will default to `None` if it's not defined in your settings, and the redirect will stop working because the common middleware will no longer be enabled. – Alasdair Oct 03 '17 at 16:07