Permalink
Browse files

Merge branch 'master' of git@github.com:bfirsh/django-class-based-views

  • Loading branch information...
2 parents 7a03a65 + 625b8cd commit 53482654b6842710a7b2ce37e4b05a7a6d470dd6 @bfirsh committed Oct 12, 2010
Showing with 62 additions and 69 deletions.
  1. +9 −16 class_based_views/base.py
  2. +9 −9 class_based_views/tests/tests/base.py
  3. +44 −44 class_based_views/tests/urls.py
View
@@ -6,9 +6,6 @@
from utils import coerce_put_post
-def quacks_like_a_request(request):
- return hasattr(request, 'method') and hasattr(request, 'path')
-
class View(object):
"""
Intentionally simple parent class for all views. Only implements
@@ -22,11 +19,6 @@ def __init__(self, *args, **kwargs):
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
- # If the first argument is a request, helpfully inform people
- # they need to instantiate the class in the URLs.
- if args and quacks_like_a_request(args[0]):
- raise RuntimeError("You must use an instance of View as a view, "
- "not the class itself.")
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in kwargs.items():
@@ -42,22 +34,23 @@ def __init__(self, *args, **kwargs):
key,
))
- def __call__(self, request, *args, **kwargs):
+ @classmethod
+ def as_view(cls, *initargs, **initkwargs):
"""
Main entry point for a request-response process.
"""
- # First, change to a copy of ourselves to stop state in
- # "self." persisting. We only need a shallow copy, really.
- self = copy.copy(self)
- self.request = request
- self.args = args
- self.kwargs = kwargs
- return self.dispatch(request, *args, **kwargs)
+ def view(request, *args, **kwargs):
+ self = cls(*initargs, **initkwargs)
+ return self.dispatch(request, *args, **kwargs)
+ return view
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method for that; if it doesn't exist,
# raise a big error.
if hasattr(self, request.method.upper()):
+ self.request = request
+ self.args = args
+ self.kwargs = kwargs
if request.method == "PUT":
coerce_put_post(request)
return getattr(self, request.method.upper())(request, *args, **kwargs)
@@ -42,19 +42,19 @@ def test_get_only(self):
"""
Test a view which only allows GET doesn't allow other methods.
"""
- self._assert_simple(SimpleView()(self.rf.get('/')))
- self.assertEqual(SimpleView()(self.rf.post('/')).status_code, 405)
- self.assertEqual(SimpleView()(
+ self._assert_simple(SimpleView.as_view()(self.rf.get('/')))
+ self.assertEqual(SimpleView.as_view()(self.rf.post('/')).status_code, 405)
+ self.assertEqual(SimpleView.as_view()(
self.rf.get('/', REQUEST_METHOD='FAKE')
).status_code, 405)
def test_get_and_post(self):
"""
Test a view which only allows both GET and POST.
"""
- self._assert_simple(SimplePostView()(self.rf.get('/')))
- self._assert_simple(SimplePostView()(self.rf.post('/')))
- self.assertEqual(SimplePostView()(
+ self._assert_simple(SimplePostView.as_view()(self.rf.get('/')))
+ self._assert_simple(SimplePostView.as_view()(self.rf.post('/')))
+ self.assertEqual(SimplePostView.as_view()(
self.rf.get('/', REQUEST_METHOD='FAKE')
).status_code, 405)
@@ -63,7 +63,7 @@ def test_calling_more_than_once(self):
Test a view can only be called once.
"""
request = self.rf.get('/')
- view = InstanceView()
+ view = InstanceView.as_view()
self.assertNotEqual(view(request), view(request))
@@ -78,12 +78,12 @@ def test_get(self):
"""
Test a view that simply renders a template on GET
"""
- self._assert_about(AboutTemplateView()(self.rf.get('/about/')))
+ self._assert_about(AboutTemplateView.as_view()(self.rf.get('/about/')))
def test_get_template_attribute(self):
"""
Test a view that renders a template on GET with the template name as
an attribute on the class.
"""
- self._assert_about(AboutTemplateAttributeView()(self.rf.get('/about/')))
+ self._assert_about(AboutTemplateAttributeView.as_view()(self.rf.get('/about/')))
@@ -8,116 +8,116 @@
# DetailView
(r'^detail/obj/$',
- views.ObjectDetail()),
+ views.ObjectDetail.as_view()),
url(r'^detail/author/(?P<pk>\d+)/$',
- views.AuthorDetail(),
+ views.AuthorDetail.as_view(),
name="author_detail"),
(r'^detail/author/byslug/(?P<slug>[\w-]+)/$',
- views.AuthorDetail()),
+ views.AuthorDetail.as_view()),
(r'^detail/author/invalid/url/$',
- views.AuthorDetail()),
+ views.AuthorDetail.as_view()),
(r'^detail/author/invalid/qs/$',
- views.AuthorDetail(queryset=None)),
+ views.AuthorDetail.as_view(queryset=None)),
# EditView
(r'^edit/authors/create/$',
- views.AuthorCreate()),
+ views.AuthorCreate.as_view()),
(r'^edit/authors/create/restricted/$',
- views.AuthorCreateRestricted()),
+ views.AuthorCreateRestricted.as_view()),
(r'^edit/author/(?P<pk>\d+)/update/$',
- views.AuthorUpdate()),
+ views.AuthorUpdate.as_view()),
(r'^edit/author/(?P<pk>\d+)/delete/$',
- views.AuthorDelete()),
+ views.AuthorDelete.as_view()),
# ArchiveView
(r'^dates/books/$',
- views.BookArchive()),
+ views.BookArchive.as_view()),
(r'^dates/books/invalid/$',
- views.BookArchive(queryset=None)),
+ views.BookArchive.as_view(queryset=None)),
# ListView
(r'^list/dict/$',
- views.DictList()),
+ views.DictList.as_view()),
url(r'^list/authors/$',
- views.AuthorList(),
+ views.AuthorList.as_view(),
name="authors_list"),
(r'^list/authors/paginated/$',
- views.PaginatedAuthorList(paginate_by=30)),
+ views.PaginatedAuthorList.as_view(paginate_by=30)),
(r'^list/authors/paginated/(?P<page>\d+)/$',
- views.PaginatedAuthorList(paginate_by=30)),
+ views.PaginatedAuthorList.as_view(paginate_by=30)),
(r'^list/authors/notempty/$',
- views.AuthorList(allow_empty=False)),
+ views.AuthorList.as_view(allow_empty=False)),
(r'^list/authors/template_object_name/$',
- views.AuthorList(template_object_name='author')),
+ views.AuthorList.as_view(template_object_name='author')),
(r'^list/authors/invalid/$',
- views.AuthorList(queryset=None)),
+ views.AuthorList.as_view(queryset=None)),
# YearView
# Mixing keyword and possitional captures below is intentional; the views
# ought to be able to accept either.
(r'^dates/books/(?P<year>\d{4})/$',
- views.BookYearArchive()),
+ views.BookYearArchive.as_view()),
(r'^dates/books/(?P<year>\d{4})/make_object_list/$',
- views.BookYearArchive(make_object_list=True)),
+ views.BookYearArchive.as_view(make_object_list=True)),
(r'^dates/books/(?P<year>\d{4})/allow_empty/$',
- views.BookYearArchive(allow_empty=True)),
+ views.BookYearArchive.as_view(allow_empty=True)),
(r'^dates/books/(?P<year>\d{4})/allow_future/$',
- views.BookYearArchive(allow_future=True)),
+ views.BookYearArchive.as_view(allow_future=True)),
(r'^dates/books/no_year/$',
- views.BookYearArchive()),
+ views.BookYearArchive.as_view()),
# MonthView
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
- views.BookMonthArchive()),
+ views.BookMonthArchive.as_view()),
(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/$',
- views.BookMonthArchive(month_format='%m')),
+ views.BookMonthArchive.as_view(month_format='%m')),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_empty/$',
- views.BookMonthArchive(allow_empty=True)),
+ views.BookMonthArchive.as_view(allow_empty=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_future/$',
- views.BookMonthArchive(allow_future=True)),
+ views.BookMonthArchive.as_view(allow_future=True)),
(r'^dates/books/(?P<year>\d{4})/no_month/$',
- views.BookMonthArchive()),
+ views.BookMonthArchive.as_view()),
# WeekView
(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$',
- views.BookWeekArchive()),
+ views.BookWeekArchive.as_view()),
(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_empty/$',
- views.BookWeekArchive(allow_empty=True)),
+ views.BookWeekArchive.as_view(allow_empty=True)),
(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_future/$',
- views.BookWeekArchive(allow_future=True)),
+ views.BookWeekArchive.as_view(allow_future=True)),
(r'^dates/books/(?P<year>\d{4})/week/no_week/$',
- views.BookWeekArchive()),
+ views.BookWeekArchive.as_view()),
# DayView
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
- views.BookDayArchive()),
+ views.BookDayArchive.as_view()),
(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$',
- views.BookDayArchive(month_format='%m')),
+ views.BookDayArchive.as_view(month_format='%m')),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty/$',
- views.BookDayArchive(allow_empty=True)),
+ views.BookDayArchive.as_view(allow_empty=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_future/$',
- views.BookDayArchive(allow_future=True)),
+ views.BookDayArchive.as_view(allow_future=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/no_day/$',
- views.BookDayArchive()),
+ views.BookDayArchive.as_view()),
# TodayView
(r'dates/books/today/$',
- views.BookTodayArchive()),
+ views.BookTodayArchive.as_view()),
(r'dates/books/today/allow_empty/$',
- views.BookTodayArchive(allow_empty=True)),
+ views.BookTodayArchive.as_view(allow_empty=True)),
# DateDetailView
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
- views.BookDetail()),
+ views.BookDetail.as_view()),
(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
- views.BookDetail(month_format='%m')),
+ views.BookDetail.as_view(month_format='%m')),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/allow_future/$',
- views.BookDetail(allow_future=True)),
+ views.BookDetail.as_view(allow_future=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/nopk/$',
- views.BookDetail()),
+ views.BookDetail.as_view()),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/byslug/(?P<slug>[\w-]+)/$',
- views.BookDetail()),
+ views.BookDetail.as_view()),
# Useful for testing redirects
(r'^accounts/login/$', 'django.contrib.auth.views.login')

0 comments on commit 5348265

Please sign in to comment.