Skip to content

Commit

Permalink
Deprecated django.views.defaults.shortcut.
Browse files Browse the repository at this point in the history
  • Loading branch information
aaugustin committed Mar 14, 2013
1 parent 2f121df commit 3f2befc
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 46 deletions.
5 changes: 5 additions & 0 deletions django/conf/urls/shortcut.py
@@ -1,5 +1,10 @@
import warnings

from django.conf.urls import patterns from django.conf.urls import patterns


warnings.warn("django.conf.urls.shortcut will be removed in Django 1.8.",
PendingDeprecationWarning)

urlpatterns = patterns('django.views', urlpatterns = patterns('django.views',
(r'^(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'defaults.shortcut'), (r'^(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'defaults.shortcut'),
) )
13 changes: 6 additions & 7 deletions django/views/defaults.py
@@ -1,3 +1,5 @@
import warnings

from django import http from django import http
from django.template import (Context, RequestContext, from django.template import (Context, RequestContext,
loader, Template, TemplateDoesNotExist) loader, Template, TemplateDoesNotExist)
Expand Down Expand Up @@ -63,12 +65,9 @@ def permission_denied(request, template_name='403.html'):




def shortcut(request, content_type_id, object_id): def shortcut(request, content_type_id, object_id):
# TODO: Remove this in Django 2.0. warnings.warn(
# This is a legacy view that depends on the contenttypes framework. "django.views.defaults.shortcut will be removed in Django 1.8. "
# The core logic was moved to django.contrib.contenttypes.views after "Import it from django.contrib.contenttypes.views instead.",
# Django 1.0, but this remains here for backwards compatibility. PendingDeprecationWarning, stacklevel=2)
# Note that the import is *within* this function, rather than being at
# module level, because we don't want to assume people have contenttypes
# installed.
from django.contrib.contenttypes.views import shortcut as real_shortcut from django.contrib.contenttypes.views import shortcut as real_shortcut
return real_shortcut(request, content_type_id, object_id) return real_shortcut(request, content_type_id, object_id)
3 changes: 3 additions & 0 deletions docs/internals/deprecation.txt
Expand Up @@ -362,6 +362,9 @@ these changes.
* Remove the backward compatible shims introduced to rename the attributes * Remove the backward compatible shims introduced to rename the attributes
``ChangeList.root_query_set`` and ``ChangeList.query_set``. ``ChangeList.root_query_set`` and ``ChangeList.query_set``.


* ``django.conf.urls.shortcut`` and ``django.views.defaults.shortcut`` will be
removed.

* The following private APIs will be removed: * The following private APIs will be removed:


- ``django.db.close_connection()`` - ``django.db.close_connection()``
Expand Down
17 changes: 17 additions & 0 deletions docs/releases/1.6.txt
Expand Up @@ -352,3 +352,20 @@ private API, it will go through a regular deprecation path.


Methods that return a ``QuerySet`` such as ``Manager.get_query_set`` or Methods that return a ``QuerySet`` such as ``Manager.get_query_set`` or
``ModelAdmin.queryset`` have been renamed to ``get_queryset``. ``ModelAdmin.queryset`` have been renamed to ``get_queryset``.

``shortcut`` view and URLconf
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``shortcut`` view was moved from ``django.views.defaults`` to
``django.contrib.contentypes.views`` shortly after the 1.0 release, but the
old location was never deprecated. This oversight was corrected in Django 1.6
and you should now use the new location.

The URLconf ``django.conf.urls.shortcut`` was also deprecated. If you're
including it in an URLconf, simply replace::

(r'^prefix/', include('django.conf.urls.shortcut')),

with::

(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contentypes.views'),
1 change: 0 additions & 1 deletion docs/topics/http/urls.txt
Expand Up @@ -330,7 +330,6 @@ itself. It includes a number of other URLconfs::
(r'^comments/', include('django.contrib.comments.urls')), (r'^comments/', include('django.contrib.comments.urls')),
(r'^community/', include('django_website.aggregator.urls')), (r'^community/', include('django_website.aggregator.urls')),
(r'^contact/', include('django_website.contact.urls')), (r'^contact/', include('django_website.contact.urls')),
(r'^r/', include('django.conf.urls.shortcut')),
# ... snip ... # ... snip ...
) )


Expand Down
Empty file.
47 changes: 47 additions & 0 deletions tests/contenttypes_tests/fixtures/testdata.json
@@ -0,0 +1,47 @@
[
{
"pk": 1,
"model": "contenttypes_tests.author",
"fields": {
"name": "Boris"
}
},
{
"pk": 1,
"model": "contenttypes_tests.article",
"fields": {
"author": 1,
"title": "Old Article",
"slug": "old_article",
"date_created": "2001-01-01 21:22:23"
}
},
{
"pk": 2,
"model": "contenttypes_tests.article",
"fields": {
"author": 1,
"title": "Current Article",
"slug": "current_article",
"date_created": "2007-09-17 21:22:23"
}
},
{
"pk": 3,
"model": "contenttypes_tests.article",
"fields": {
"author": 1,
"title": "Future Article",
"slug": "future_article",
"date_created": "3000-01-01 21:22:23"
}
},
{
"pk": 1,
"model": "sites.site",
"fields": {
"domain": "testserver",
"name": "testserver"
}
}
]
24 changes: 24 additions & 0 deletions tests/contenttypes_tests/models.py
@@ -0,0 +1,24 @@
from __future__ import absolute_import, unicode_literals

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible
class Author(models.Model):
name = models.CharField(max_length=100)

def __str__(self):
return self.name

def get_absolute_url(self):
return '/views/authors/%s/' % self.id

@python_2_unicode_compatible
class Article(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField()
author = models.ForeignKey(Author)
date_created = models.DateTimeField()

def __str__(self):
return self.title
47 changes: 47 additions & 0 deletions tests/contenttypes_tests/tests.py
@@ -0,0 +1,47 @@
from __future__ import absolute_import, unicode_literals

from django.contrib.contenttypes.models import ContentType
from django.test import TestCase

from .models import Author, Article

class ContentTypesViewsTests(TestCase):
fixtures = ['testdata.json']
urls = 'contenttypes_tests.urls'

def test_shortcut_with_absolute_url(self):
"Can view a shortcut for an Author object that has a get_absolute_url method"
for obj in Author.objects.all():
short_url = '/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, obj.pk)
response = self.client.get(short_url)
self.assertRedirects(response, 'http://testserver%s' % obj.get_absolute_url(),
status_code=302, target_status_code=404)

def test_shortcut_no_absolute_url(self):
"Shortcuts for an object that has no get_absolute_url method raises 404"
for obj in Article.objects.all():
short_url = '/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, obj.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_wrong_type_pk(self):
short_url = '/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, 'nobody/expects')
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_shortcut_bad_pk(self):
short_url = '/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, '42424242')
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_nonint_content_type(self):
an_author = Author.objects.all()[0]
short_url = '/shortcut/%s/%s/' % ('spam', an_author.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_bad_content_type(self):
an_author = Author.objects.all()[0]
short_url = '/shortcut/%s/%s/' % (42424242, an_author.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)
7 changes: 7 additions & 0 deletions tests/contenttypes_tests/urls.py
@@ -0,0 +1,7 @@
from __future__ import absolute_import, unicode_literals

from django.conf.urls import patterns

urlpatterns = patterns('',
(r'^shortcut/(\d+)/(.*)/$', 'django.contrib.contenttypes.views.shortcut'),
)
37 changes: 0 additions & 37 deletions tests/view_tests/tests/defaults.py
Expand Up @@ -13,43 +13,6 @@ class DefaultsTests(TestCase):
non_existing_urls = ['/views/non_existing_url/', # this is in urls.py non_existing_urls = ['/views/non_existing_url/', # this is in urls.py
'/views/other_non_existing_url/'] # this NOT in urls.py '/views/other_non_existing_url/'] # this NOT in urls.py


def test_shortcut_with_absolute_url(self):
"Can view a shortcut for an Author object that has a get_absolute_url method"
for obj in Author.objects.all():
short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, obj.pk)
response = self.client.get(short_url)
self.assertRedirects(response, 'http://testserver%s' % obj.get_absolute_url(),
status_code=302, target_status_code=404)

def test_shortcut_no_absolute_url(self):
"Shortcuts for an object that has no get_absolute_url method raises 404"
for obj in Article.objects.all():
short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, obj.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_wrong_type_pk(self):
short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, 'nobody/expects')
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_shortcut_bad_pk(self):
short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, '42424242')
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_nonint_content_type(self):
an_author = Author.objects.all()[0]
short_url = '/views/shortcut/%s/%s/' % ('spam', an_author.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_bad_content_type(self):
an_author = Author.objects.all()[0]
short_url = '/views/shortcut/%s/%s/' % (42424242, an_author.pk)
response = self.client.get(short_url)
self.assertEqual(response.status_code, 404)

def test_page_not_found(self): def test_page_not_found(self):
"A 404 status is returned by the page_not_found view" "A 404 status is returned by the page_not_found view"
for url in self.non_existing_urls: for url in self.non_existing_urls:
Expand Down
1 change: 0 additions & 1 deletion tests/view_tests/urls.py
Expand Up @@ -42,7 +42,6 @@
(r'^$', views.index_page), (r'^$', views.index_page),


# Default views # Default views
(r'^shortcut/(\d+)/(.*)/$', 'django.views.defaults.shortcut'),
(r'^non_existing_url/', 'django.views.defaults.page_not_found'), (r'^non_existing_url/', 'django.views.defaults.page_not_found'),
(r'^server_error/', 'django.views.defaults.server_error'), (r'^server_error/', 'django.views.defaults.server_error'),


Expand Down

0 comments on commit 3f2befc

Please sign in to comment.