diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-07-18 19:45:00 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-07-18 19:45:00 +0000 |
| commit | 7997133a3dbf67edcb5a7588c1c049d181a4e61a (patch) | |
| tree | 3e560d110843a6458e86e8c97718570244a631ee /tests/regressiontests/views | |
| parent | cd80ce7a3d7040e15f567a315850a744619c0d96 (diff) | |
Fixed #3639: updated generic create_update views to use newforms. This is a backwards-incompatible change.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@7952 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/regressiontests/views')
| -rw-r--r-- | tests/regressiontests/views/fixtures/testdata.json | 29 | ||||
| -rw-r--r-- | tests/regressiontests/views/models.py | 24 | ||||
| -rw-r--r-- | tests/regressiontests/views/tests/__init__.py | 3 | ||||
| -rw-r--r-- | tests/regressiontests/views/tests/generic/create_update.py | 211 | ||||
| -rw-r--r-- | tests/regressiontests/views/urls.py | 72 | ||||
| -rw-r--r-- | tests/regressiontests/views/views.py | 24 |
6 files changed, 336 insertions, 27 deletions
diff --git a/tests/regressiontests/views/fixtures/testdata.json b/tests/regressiontests/views/fixtures/testdata.json index 449e91913a..e3fed9eac7 100644 --- a/tests/regressiontests/views/fixtures/testdata.json +++ b/tests/regressiontests/views/fixtures/testdata.json @@ -1,5 +1,23 @@ [ { + "pk": "1", + "model": "auth.user", + "fields": { + "username": "testclient", + "first_name": "Test", + "last_name": "Client", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2006-12-17 07:03:31", + "groups": [], + "user_permissions": [], + "password": "sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161", + "email": "testclient@example.com", + "date_joined": "2006-12-17 07:03:31" + } + }, + { "pk": 1, "model": "views.article", "fields": { @@ -29,7 +47,16 @@ "date_created": "3000-01-01 21:22:23" } }, - + { + "pk": 1, + "model": "views.urlarticle", + "fields": { + "author": 1, + "title": "Old Article", + "slug": "old_article", + "date_created": "2001-01-01 21:22:23" + } + }, { "pk": 1, "model": "views.author", diff --git a/tests/regressiontests/views/models.py b/tests/regressiontests/views/models.py index 4bed1f3bde..ce31778177 100644 --- a/tests/regressiontests/views/models.py +++ b/tests/regressiontests/views/models.py @@ -1,9 +1,8 @@ """ -Regression tests for Django built-in views +Regression tests for Django built-in views. """ from django.db import models -from django.conf import settings class Author(models.Model): name = models.CharField(max_length=100) @@ -14,13 +13,28 @@ class Author(models.Model): def get_absolute_url(self): return '/views/authors/%s/' % self.id - -class Article(models.Model): +class BaseArticle(models.Model): + """ + An abstract article Model so that we can create article models with and + without a get_absolute_url method (for create_update generic views tests). + """ title = models.CharField(max_length=100) slug = models.SlugField() author = models.ForeignKey(Author) date_created = models.DateTimeField() - + + class Meta: + abstract = True + def __unicode__(self): return self.title +class Article(BaseArticle): + pass + +class UrlArticle(BaseArticle): + """ + An Article class with a get_absolute_url defined. + """ + def get_absolute_url(self): + return '/urlarticles/%s/' % self.slug diff --git a/tests/regressiontests/views/tests/__init__.py b/tests/regressiontests/views/tests/__init__.py index 2c8c5b4a92..9964cd5833 100644 --- a/tests/regressiontests/views/tests/__init__.py +++ b/tests/regressiontests/views/tests/__init__.py @@ -1,4 +1,5 @@ from defaults import * from i18n import * from static import * -from generic.date_based import *
\ No newline at end of file +from generic.date_based import * +from generic.create_update import * diff --git a/tests/regressiontests/views/tests/generic/create_update.py b/tests/regressiontests/views/tests/generic/create_update.py new file mode 100644 index 0000000000..3975c65706 --- /dev/null +++ b/tests/regressiontests/views/tests/generic/create_update.py @@ -0,0 +1,211 @@ +import datetime + +from django.test import TestCase +from django.core.exceptions import ImproperlyConfigured +from regressiontests.views.models import Article, UrlArticle + +class CreateObjectTest(TestCase): + + fixtures = ['testdata.json'] + + def test_login_required_view(self): + """ + Verifies that an unauthenticated user attempting to access a + login_required view gets redirected to the login page and that + an authenticated user is let through. + """ + view_url = '/views/create_update/member/create/article/' + response = self.client.get(view_url) + self.assertRedirects(response, '/accounts/login/?next=%s' % view_url) + # Now login and try again. + login = self.client.login(username='testclient', password='password') + self.failUnless(login, 'Could not log in') + response = self.client.get(view_url) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'views/article_form.html') + + def test_create_article_display_page(self): + """ + Ensures the generic view returned the page and contains a form. + """ + view_url = '/views/create_update/create/article/' + response = self.client.get(view_url) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'views/article_form.html') + if not response.context.get('form'): + self.fail('No form found in the response.') + + def test_create_article_with_errors(self): + """ + POSTs a form that contains validation errors. + """ + view_url = '/views/create_update/create/article/' + num_articles = Article.objects.count() + response = self.client.post(view_url, { + 'title': 'My First Article', + }) + self.assertFormError(response, 'form', 'slug', [u'This field is required.']) + self.assertTemplateUsed(response, 'views/article_form.html') + self.assertEqual(num_articles, Article.objects.count(), + "Number of Articles should not have changed.") + + def test_create_custom_save_article(self): + """ + Creates a new article using a custom form class with a save method + that alters the slug entered. + """ + view_url = '/views/create_update/create_custom/article/' + response = self.client.post(view_url, { + 'title': 'Test Article', + 'slug': 'this-should-get-replaced', + 'author': 1, + 'date_created': datetime.datetime(2007, 6, 25), + }) + self.assertRedirects(response, + '/views/create_update/view/article/some-other-slug/', + target_status_code=404) + +class UpdateDeleteObjectTest(TestCase): + + fixtures = ['testdata.json'] + + def test_update_object_form_display(self): + """ + Verifies that the form was created properly and with initial values. + """ + response = self.client.get('/views/create_update/update/article/old_article/') + self.assertTemplateUsed(response, 'views/article_form.html') + self.assertEquals(unicode(response.context['form']['title']), + u'<input id="id_title" type="text" name="title" value="Old Article" maxlength="100" />') + + def test_update_object(self): + """ + Verifies the updating of an Article. + """ + response = self.client.post('/views/create_update/update/article/old_article/', { + 'title': 'Another Article', + 'slug': 'another-article-slug', + 'author': 1, + 'date_created': datetime.datetime(2007, 6, 25), + }) + article = Article.objects.get(pk=1) + self.assertEquals(article.title, "Another Article") + + def test_delete_object_confirm(self): + """ + Verifies the confirm deletion page is displayed using a GET. + """ + response = self.client.get('/views/create_update/delete/article/old_article/') + self.assertTemplateUsed(response, 'views/article_confirm_delete.html') + + def test_delete_object(self): + """ + Verifies the object actually gets deleted on a POST. + """ + view_url = '/views/create_update/delete/article/old_article/' + response = self.client.post(view_url) + try: + Article.objects.get(slug='old_article') + except Article.DoesNotExist: + pass + else: + self.fail('Object was not deleted.') + +class PostSaveRedirectTests(TestCase): + """ + Verifies that the views redirect to the correct locations depending on + if a post_save_redirect was passed and a get_absolute_url method exists + on the Model. + """ + + fixtures = ['testdata.json'] + article_model = Article + + create_url = '/views/create_update/create/article/' + update_url = '/views/create_update/update/article/old_article/' + delete_url = '/views/create_update/delete/article/old_article/' + + create_redirect = '/views/create_update/view/article/my-first-article/' + update_redirect = '/views/create_update/view/article/another-article-slug/' + delete_redirect = '/views/create_update/' + + def test_create_article(self): + num_articles = self.article_model.objects.count() + response = self.client.post(self.create_url, { + 'title': 'My First Article', + 'slug': 'my-first-article', + 'author': '1', + 'date_created': datetime.datetime(2007, 6, 25), + }) + self.assertRedirects(response, self.create_redirect, + target_status_code=404) + self.assertEqual(num_articles + 1, self.article_model.objects.count(), + "A new Article should have been created.") + + def test_update_article(self): + num_articles = self.article_model.objects.count() + response = self.client.post(self.update_url, { + 'title': 'Another Article', + 'slug': 'another-article-slug', + 'author': 1, + 'date_created': datetime.datetime(2007, 6, 25), + }) + self.assertRedirects(response, self.update_redirect, + target_status_code=404) + self.assertEqual(num_articles, self.article_model.objects.count(), + "A new Article should not have been created.") + + def test_delete_article(self): + num_articles = self.article_model.objects.count() + response = self.client.post(self.delete_url) + self.assertRedirects(response, self.delete_redirect, + target_status_code=404) + self.assertEqual(num_articles - 1, self.article_model.objects.count(), + "An Article should have been deleted.") + +class NoPostSaveNoAbsoluteUrl(PostSaveRedirectTests): + """ + Tests that when no post_save_redirect is passed and no get_absolute_url + method exists on the Model that the view raises an ImproperlyConfigured + error. + """ + + create_url = '/views/create_update/no_redirect/create/article/' + update_url = '/views/create_update/no_redirect/update/article/old_article/' + + def test_create_article(self): + self.assertRaises(ImproperlyConfigured, + super(NoPostSaveNoAbsoluteUrl, self).test_create_article) + + def test_update_article(self): + self.assertRaises(ImproperlyConfigured, + super(NoPostSaveNoAbsoluteUrl, self).test_update_article) + + def test_delete_article(self): + """ + The delete_object view requires a post_delete_redirect, so skip testing + here. + """ + pass + +class AbsoluteUrlNoPostSave(PostSaveRedirectTests): + """ + Tests that the views redirect to the Model's get_absolute_url when no + post_save_redirect is passed. + """ + + # Article model with get_absolute_url method. + article_model = UrlArticle + + create_url = '/views/create_update/no_url/create/article/' + update_url = '/views/create_update/no_url/update/article/old_article/' + + create_redirect = '/urlarticles/my-first-article/' + update_redirect = '/urlarticles/another-article-slug/' + + def test_delete_article(self): + """ + The delete_object view requires a post_delete_redirect, so skip testing + here. + """ + pass diff --git a/tests/regressiontests/views/urls.py b/tests/regressiontests/views/urls.py index 5ef0c5129d..3a4700b998 100644 --- a/tests/regressiontests/views/urls.py +++ b/tests/regressiontests/views/urls.py @@ -5,6 +5,7 @@ from django.conf.urls.defaults import * from models import * import views + base_dir = path.dirname(path.abspath(__file__)) media_dir = path.join(base_dir, 'media') locale_dir = path.join(base_dir, 'locale') @@ -14,35 +15,66 @@ js_info_dict = { 'packages': ('regressiontests.views',), } -date_based_info_dict = { - 'queryset': Article.objects.all(), - 'date_field': 'date_created', - 'month_format': '%m', -} +date_based_info_dict = { + 'queryset': Article.objects.all(), + 'date_field': 'date_created', + 'month_format': '%m', +} urlpatterns = patterns('', (r'^$', views.index_page), - + # Default views (r'^shortcut/(\d+)/(.*)/$', 'django.views.defaults.shortcut'), (r'^non_existing_url/', 'django.views.defaults.page_not_found'), (r'^server_error/', 'django.views.defaults.server_error'), - + # i18n views - (r'^i18n/', include('django.conf.urls.i18n')), + (r'^i18n/', include('django.conf.urls.i18n')), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), - + # Static views (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': media_dir}), - - # Date-based generic views - (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$', - 'django.views.generic.date_based.object_detail', - dict(slug_field='slug', **date_based_info_dict)), - (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/allow_future/$', - 'django.views.generic.date_based.object_detail', - dict(allow_future=True, slug_field='slug', **date_based_info_dict)), - (r'^date_based/archive_month/(?P<year>\d{4})/(?P<month>\d{1,2})/$', - 'django.views.generic.date_based.archive_month', - date_based_info_dict), +) + +# Date-based generic views. +urlpatterns += patterns('django.views.generic.date_based', + (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$', + 'object_detail', + dict(slug_field='slug', **date_based_info_dict)), + (r'^date_based/object_detail/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/allow_future/$', + 'object_detail', + dict(allow_future=True, slug_field='slug', **date_based_info_dict)), + (r'^date_based/archive_month/(?P<year>\d{4})/(?P<month>\d{1,2})/$', + 'archive_month', + date_based_info_dict), +) + +# crud generic views. + +urlpatterns += patterns('django.views.generic.create_update', + (r'^create_update/member/create/article/$', 'create_object', + dict(login_required=True, model=Article)), + (r'^create_update/create/article/$', 'create_object', + dict(post_save_redirect='/views/create_update/view/article/%(slug)s/', + model=Article)), + (r'^create_update/update/article/(?P<slug>[-\w]+)/$', 'update_object', + dict(post_save_redirect='/views/create_update/view/article/%(slug)s/', + slug_field='slug', model=Article)), + (r'^create_update/create_custom/article/$', views.custom_create), + (r'^create_update/delete/article/(?P<slug>[-\w]+)/$', 'delete_object', + dict(post_delete_redirect='/views/create_update/', slug_field='slug', + model=Article)), + + # No post_save_redirect and no get_absolute_url on model. + (r'^create_update/no_redirect/create/article/$', 'create_object', + dict(model=Article)), + (r'^create_update/no_redirect/update/article/(?P<slug>[-\w]+)/$', + 'update_object', dict(slug_field='slug', model=Article)), + + # get_absolute_url on model, but no passed post_save_redirect. + (r'^create_update/no_url/create/article/$', 'create_object', + dict(model=UrlArticle)), + (r'^create_update/no_url/update/article/(?P<slug>[-\w]+)/$', + 'update_object', dict(slug_field='slug', model=UrlArticle)), ) diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py index 956432e7d5..eda8aabc50 100644 --- a/tests/regressiontests/views/views.py +++ b/tests/regressiontests/views/views.py @@ -1,5 +1,29 @@ from django.http import HttpResponse +import django.newforms as forms +from django.views.generic.create_update import create_object + +from models import Article + def index_page(request): """Dummy index page""" return HttpResponse('<html><body>Dummy page</body></html>') + + +def custom_create(request): + """ + Calls create_object generic view with a custom form class. + """ + class SlugChangingArticleForm(forms.ModelForm): + """Custom form class to overwrite the slug.""" + + class Meta: + model = Article + + def save(self, *args, **kwargs): + self.cleaned_data['slug'] = 'some-other-slug' + return super(SlugChangingArticleForm, self).save(*args, **kwargs) + + return create_object(request, + post_save_redirect='/views/create_update/view/article/%(slug)s/', + form_class=SlugChangingArticleForm) |
