diff options
Diffstat (limited to 'parts/django/tests/modeltests')
228 files changed, 0 insertions, 16291 deletions
diff --git a/parts/django/tests/modeltests/__init__.py b/parts/django/tests/modeltests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/aggregation/__init__.py b/parts/django/tests/modeltests/aggregation/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/aggregation/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/aggregation/fixtures/initial_data.json b/parts/django/tests/modeltests/aggregation/fixtures/initial_data.json deleted file mode 100644 index a002100..0000000 --- a/parts/django/tests/modeltests/aggregation/fixtures/initial_data.json +++ /dev/null @@ -1,243 +0,0 @@ -[ - { - "pk": 1, - "model": "aggregation.publisher", - "fields": { - "name": "Apress", - "num_awards": 3 - } - }, - { - "pk": 2, - "model": "aggregation.publisher", - "fields": { - "name": "Sams", - "num_awards": 1 - } - }, - { - "pk": 3, - "model": "aggregation.publisher", - "fields": { - "name": "Prentice Hall", - "num_awards": 7 - } - }, - { - "pk": 4, - "model": "aggregation.publisher", - "fields": { - "name": "Morgan Kaufmann", - "num_awards": 9 - } - }, - { - "pk": 5, - "model": "aggregation.publisher", - "fields": { - "name": "Jonno's House of Books", - "num_awards": 0 - } - }, - { - "pk": 1, - "model": "aggregation.book", - "fields": { - "publisher": 1, - "isbn": "159059725", - "name": "The Definitive Guide to Django: Web Development Done Right", - "price": "30.00", - "rating": 4.5, - "authors": [1, 2], - "contact": 1, - "pages": 447, - "pubdate": "2007-12-6" - } - }, - { - "pk": 2, - "model": "aggregation.book", - "fields": { - "publisher": 2, - "isbn": "067232959", - "name": "Sams Teach Yourself Django in 24 Hours", - "price": "23.09", - "rating": 3.0, - "authors": [3], - "contact": 3, - "pages": 528, - "pubdate": "2008-3-3" - } - }, - { - "pk": 3, - "model": "aggregation.book", - "fields": { - "publisher": 1, - "isbn": "159059996", - "name": "Practical Django Projects", - "price": "29.69", - "rating": 4.0, - "authors": [4], - "contact": 4, - "pages": 300, - "pubdate": "2008-6-23" - } - }, - { - "pk": 4, - "model": "aggregation.book", - "fields": { - "publisher": 3, - "isbn": "013235613", - "name": "Python Web Development with Django", - "price": "29.69", - "rating": 4.0, - "authors": [5, 6, 7], - "contact": 5, - "pages": 350, - "pubdate": "2008-11-3" - } - }, - { - "pk": 5, - "model": "aggregation.book", - "fields": { - "publisher": 3, - "isbn": "013790395", - "name": "Artificial Intelligence: A Modern Approach", - "price": "82.80", - "rating": 4.0, - "authors": [8, 9], - "contact": 8, - "pages": 1132, - "pubdate": "1995-1-15" - } - }, - { - "pk": 6, - "model": "aggregation.book", - "fields": { - "publisher": 4, - "isbn": "155860191", - "name": "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp", - "price": "75.00", - "rating": 5.0, - "authors": [8], - "contact": 8, - "pages": 946, - "pubdate": "1991-10-15" - } - }, - { - "pk": 1, - "model": "aggregation.store", - "fields": { - "books": [1, 2, 3, 4, 5, 6], - "name": "Amazon.com", - "original_opening": "1994-4-23 9:17:42", - "friday_night_closing": "23:59:59" - } - }, - { - "pk": 2, - "model": "aggregation.store", - "fields": { - "books": [1, 3, 5, 6], - "name": "Books.com", - "original_opening": "2001-3-15 11:23:37", - "friday_night_closing": "23:59:59" - } - }, - { - "pk": 3, - "model": "aggregation.store", - "fields": { - "books": [3, 4, 6], - "name": "Mamma and Pappa's Books", - "original_opening": "1945-4-25 16:24:14", - "friday_night_closing": "21:30:00" - } - }, - { - "pk": 1, - "model": "aggregation.author", - "fields": { - "age": 34, - "friends": [2, 4], - "name": "Adrian Holovaty" - } - }, - { - "pk": 2, - "model": "aggregation.author", - "fields": { - "age": 35, - "friends": [1, 7], - "name": "Jacob Kaplan-Moss" - } - }, - { - "pk": 3, - "model": "aggregation.author", - "fields": { - "age": 45, - "friends": [], - "name": "Brad Dayley" - } - }, - { - "pk": 4, - "model": "aggregation.author", - "fields": { - "age": 29, - "friends": [1], - "name": "James Bennett" - } - }, - { - "pk": 5, - "model": "aggregation.author", - "fields": { - "age": 37, - "friends": [6, 7], - "name": "Jeffrey Forcier" - } - }, - { - "pk": 6, - "model": "aggregation.author", - "fields": { - "age": 29, - "friends": [5, 7], - "name": "Paul Bissex" - } - }, - { - "pk": 7, - "model": "aggregation.author", - "fields": { - "age": 25, - "friends": [2, 5, 6], - "name": "Wesley J. Chun" - } - }, - { - "pk": 8, - "model": "aggregation.author", - "fields": { - "age": 57, - "friends": [9], - "name": "Peter Norvig" - } - }, - { - "pk": 9, - "model": "aggregation.author", - "fields": { - "age": 46, - "friends": [8], - "name": "Stuart Russell" - } - } -] diff --git a/parts/django/tests/modeltests/aggregation/models.py b/parts/django/tests/modeltests/aggregation/models.py deleted file mode 100644 index ccc1289..0000000 --- a/parts/django/tests/modeltests/aggregation/models.py +++ /dev/null @@ -1,42 +0,0 @@ -# coding: utf-8 -from django.db import models - - -class Author(models.Model): - name = models.CharField(max_length=100) - age = models.IntegerField() - friends = models.ManyToManyField('self', blank=True) - - def __unicode__(self): - return self.name - -class Publisher(models.Model): - name = models.CharField(max_length=255) - num_awards = models.IntegerField() - - def __unicode__(self): - return self.name - -class Book(models.Model): - isbn = models.CharField(max_length=9) - name = models.CharField(max_length=255) - pages = models.IntegerField() - rating = models.FloatField() - price = models.DecimalField(decimal_places=2, max_digits=6) - authors = models.ManyToManyField(Author) - contact = models.ForeignKey(Author, related_name='book_contact_set') - publisher = models.ForeignKey(Publisher) - pubdate = models.DateField() - - def __unicode__(self): - return self.name - -class Store(models.Model): - name = models.CharField(max_length=255) - books = models.ManyToManyField(Book) - original_opening = models.DateTimeField() - friday_night_closing = models.TimeField() - - def __unicode__(self): - return self.name - diff --git a/parts/django/tests/modeltests/aggregation/tests.py b/parts/django/tests/modeltests/aggregation/tests.py deleted file mode 100644 index c830368..0000000 --- a/parts/django/tests/modeltests/aggregation/tests.py +++ /dev/null @@ -1,565 +0,0 @@ -import datetime -from decimal import Decimal - -from django.db.models import Avg, Sum, Count, Max, Min -from django.test import TestCase, Approximate - -from models import Author, Publisher, Book, Store - - -class BaseAggregateTestCase(TestCase): - fixtures = ["initial_data.json"] - - def test_empty_aggregate(self): - self.assertEqual(Author.objects.all().aggregate(), {}) - - def test_single_aggregate(self): - vals = Author.objects.aggregate(Avg("age")) - self.assertEqual(vals, {"age__avg": Approximate(37.4, places=1)}) - - def test_multiple_aggregates(self): - vals = Author.objects.aggregate(Sum("age"), Avg("age")) - self.assertEqual(vals, {"age__sum": 337, "age__avg": Approximate(37.4, places=1)}) - - def test_filter_aggregate(self): - vals = Author.objects.filter(age__gt=29).aggregate(Sum("age")) - self.assertEqual(len(vals), 1) - self.assertEqual(vals["age__sum"], 254) - - def test_related_aggregate(self): - vals = Author.objects.aggregate(Avg("friends__age")) - self.assertEqual(len(vals), 1) - self.assertAlmostEqual(vals["friends__age__avg"], 34.07, places=2) - - vals = Book.objects.filter(rating__lt=4.5).aggregate(Avg("authors__age")) - self.assertEqual(len(vals), 1) - self.assertAlmostEqual(vals["authors__age__avg"], 38.2857, places=2) - - vals = Author.objects.all().filter(name__contains="a").aggregate(Avg("book__rating")) - self.assertEqual(len(vals), 1) - self.assertEqual(vals["book__rating__avg"], 4.0) - - vals = Book.objects.aggregate(Sum("publisher__num_awards")) - self.assertEqual(len(vals), 1) - self.assertEquals(vals["publisher__num_awards__sum"], 30) - - vals = Publisher.objects.aggregate(Sum("book__price")) - self.assertEqual(len(vals), 1) - self.assertEqual(vals["book__price__sum"], Decimal("270.27")) - - def test_aggregate_multi_join(self): - vals = Store.objects.aggregate(Max("books__authors__age")) - self.assertEqual(len(vals), 1) - self.assertEqual(vals["books__authors__age__max"], 57) - - vals = Author.objects.aggregate(Min("book__publisher__num_awards")) - self.assertEqual(len(vals), 1) - self.assertEqual(vals["book__publisher__num_awards__min"], 1) - - def test_aggregate_alias(self): - vals = Store.objects.filter(name="Amazon.com").aggregate(amazon_mean=Avg("books__rating")) - self.assertEqual(len(vals), 1) - self.assertAlmostEqual(vals["amazon_mean"], 4.08, places=2) - - def test_annotate_basic(self): - self.assertQuerysetEqual( - Book.objects.annotate().order_by('pk'), [ - "The Definitive Guide to Django: Web Development Done Right", - "Sams Teach Yourself Django in 24 Hours", - "Practical Django Projects", - "Python Web Development with Django", - "Artificial Intelligence: A Modern Approach", - "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp" - ], - lambda b: b.name - ) - - books = Book.objects.annotate(mean_age=Avg("authors__age")) - b = books.get(pk=1) - self.assertEqual( - b.name, - u'The Definitive Guide to Django: Web Development Done Right' - ) - self.assertEqual(b.mean_age, 34.5) - - def test_annotate_m2m(self): - books = Book.objects.filter(rating__lt=4.5).annotate(Avg("authors__age")).order_by("name") - self.assertQuerysetEqual( - books, [ - (u'Artificial Intelligence: A Modern Approach', 51.5), - (u'Practical Django Projects', 29.0), - (u'Python Web Development with Django', Approximate(30.3, places=1)), - (u'Sams Teach Yourself Django in 24 Hours', 45.0) - ], - lambda b: (b.name, b.authors__age__avg), - ) - - books = Book.objects.annotate(num_authors=Count("authors")).order_by("name") - self.assertQuerysetEqual( - books, [ - (u'Artificial Intelligence: A Modern Approach', 2), - (u'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 1), - (u'Practical Django Projects', 1), - (u'Python Web Development with Django', 3), - (u'Sams Teach Yourself Django in 24 Hours', 1), - (u'The Definitive Guide to Django: Web Development Done Right', 2) - ], - lambda b: (b.name, b.num_authors) - ) - - def test_backwards_m2m_annotate(self): - authors = Author.objects.filter(name__contains="a").annotate(Avg("book__rating")).order_by("name") - self.assertQuerysetEqual( - authors, [ - (u'Adrian Holovaty', 4.5), - (u'Brad Dayley', 3.0), - (u'Jacob Kaplan-Moss', 4.5), - (u'James Bennett', 4.0), - (u'Paul Bissex', 4.0), - (u'Stuart Russell', 4.0) - ], - lambda a: (a.name, a.book__rating__avg) - ) - - authors = Author.objects.annotate(num_books=Count("book")).order_by("name") - self.assertQuerysetEqual( - authors, [ - (u'Adrian Holovaty', 1), - (u'Brad Dayley', 1), - (u'Jacob Kaplan-Moss', 1), - (u'James Bennett', 1), - (u'Jeffrey Forcier', 1), - (u'Paul Bissex', 1), - (u'Peter Norvig', 2), - (u'Stuart Russell', 1), - (u'Wesley J. Chun', 1) - ], - lambda a: (a.name, a.num_books) - ) - - def test_reverse_fkey_annotate(self): - books = Book.objects.annotate(Sum("publisher__num_awards")).order_by("name") - self.assertQuerysetEqual( - books, [ - (u'Artificial Intelligence: A Modern Approach', 7), - (u'Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp', 9), - (u'Practical Django Projects', 3), - (u'Python Web Development with Django', 7), - (u'Sams Teach Yourself Django in 24 Hours', 1), - (u'The Definitive Guide to Django: Web Development Done Right', 3) - ], - lambda b: (b.name, b.publisher__num_awards__sum) - ) - - publishers = Publisher.objects.annotate(Sum("book__price")).order_by("name") - self.assertQuerysetEqual( - publishers, [ - (u'Apress', Decimal("59.69")), - (u"Jonno's House of Books", None), - (u'Morgan Kaufmann', Decimal("75.00")), - (u'Prentice Hall', Decimal("112.49")), - (u'Sams', Decimal("23.09")) - ], - lambda p: (p.name, p.book__price__sum) - ) - - def test_annotate_values(self): - books = list(Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values()) - self.assertEqual( - books, [ - { - "contact_id": 1, - "id": 1, - "isbn": "159059725", - "mean_age": 34.5, - "name": "The Definitive Guide to Django: Web Development Done Right", - "pages": 447, - "price": Approximate(Decimal("30")), - "pubdate": datetime.date(2007, 12, 6), - "publisher_id": 1, - "rating": 4.5, - } - ] - ) - - books = Book.objects.filter(pk=1).annotate(mean_age=Avg('authors__age')).values('pk', 'isbn', 'mean_age') - self.assertEqual( - list(books), [ - { - "pk": 1, - "isbn": "159059725", - "mean_age": 34.5, - } - ] - ) - - books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values("name") - self.assertEqual( - list(books), [ - { - "name": "The Definitive Guide to Django: Web Development Done Right" - } - ] - ) - - books = Book.objects.filter(pk=1).values().annotate(mean_age=Avg('authors__age')) - self.assertEqual( - list(books), [ - { - "contact_id": 1, - "id": 1, - "isbn": "159059725", - "mean_age": 34.5, - "name": "The Definitive Guide to Django: Web Development Done Right", - "pages": 447, - "price": Approximate(Decimal("30")), - "pubdate": datetime.date(2007, 12, 6), - "publisher_id": 1, - "rating": 4.5, - } - ] - ) - - books = Book.objects.values("rating").annotate(n_authors=Count("authors__id"), mean_age=Avg("authors__age")).order_by("rating") - self.assertEqual( - list(books), [ - { - "rating": 3.0, - "n_authors": 1, - "mean_age": 45.0, - }, - { - "rating": 4.0, - "n_authors": 6, - "mean_age": Approximate(37.16, places=1) - }, - { - "rating": 4.5, - "n_authors": 2, - "mean_age": 34.5, - }, - { - "rating": 5.0, - "n_authors": 1, - "mean_age": 57.0, - } - ] - ) - - authors = Author.objects.annotate(Avg("friends__age")).order_by("name") - self.assertEqual(len(authors), 9) - self.assertQuerysetEqual( - authors, [ - (u'Adrian Holovaty', 32.0), - (u'Brad Dayley', None), - (u'Jacob Kaplan-Moss', 29.5), - (u'James Bennett', 34.0), - (u'Jeffrey Forcier', 27.0), - (u'Paul Bissex', 31.0), - (u'Peter Norvig', 46.0), - (u'Stuart Russell', 57.0), - (u'Wesley J. Chun', Approximate(33.66, places=1)) - ], - lambda a: (a.name, a.friends__age__avg) - ) - - def test_count(self): - vals = Book.objects.aggregate(Count("rating")) - self.assertEqual(vals, {"rating__count": 6}) - - vals = Book.objects.aggregate(Count("rating", distinct=True)) - self.assertEqual(vals, {"rating__count": 4}) - - def test_fkey_aggregate(self): - explicit = list(Author.objects.annotate(Count('book__id'))) - implicit = list(Author.objects.annotate(Count('book'))) - self.assertEqual(explicit, implicit) - - def test_annotate_ordering(self): - books = Book.objects.values('rating').annotate(oldest=Max('authors__age')).order_by('oldest', 'rating') - self.assertEqual( - list(books), [ - { - "rating": 4.5, - "oldest": 35, - }, - { - "rating": 3.0, - "oldest": 45 - }, - { - "rating": 4.0, - "oldest": 57, - }, - { - "rating": 5.0, - "oldest": 57, - } - ] - ) - - books = Book.objects.values("rating").annotate(oldest=Max("authors__age")).order_by("-oldest", "-rating") - self.assertEqual( - list(books), [ - { - "rating": 5.0, - "oldest": 57, - }, - { - "rating": 4.0, - "oldest": 57, - }, - { - "rating": 3.0, - "oldest": 45, - }, - { - "rating": 4.5, - "oldest": 35, - } - ] - ) - - def test_aggregate_annotation(self): - vals = Book.objects.annotate(num_authors=Count("authors__id")).aggregate(Avg("num_authors")) - self.assertEqual(vals, {"num_authors__avg": Approximate(1.66, places=1)}) - - def test_filtering(self): - p = Publisher.objects.create(name='Expensive Publisher', num_awards=0) - Book.objects.create( - name='ExpensiveBook1', - pages=1, - isbn='111', - rating=3.5, - price=Decimal("1000"), - publisher=p, - contact_id=1, - pubdate=datetime.date(2008,12,1) - ) - Book.objects.create( - name='ExpensiveBook2', - pages=1, - isbn='222', - rating=4.0, - price=Decimal("1000"), - publisher=p, - contact_id=1, - pubdate=datetime.date(2008,12,2) - ) - Book.objects.create( - name='ExpensiveBook3', - pages=1, - isbn='333', - rating=4.5, - price=Decimal("35"), - publisher=p, - contact_id=1, - pubdate=datetime.date(2008,12,3) - ) - - publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Prentice Hall", - "Expensive Publisher", - ], - lambda p: p.name, - ) - - publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Apress", - "Sams", - "Prentice Hall", - "Expensive Publisher", - ], - lambda p: p.name - ) - - publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1, book__price__lt=Decimal("40.0")).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Prentice Hall", - "Expensive Publisher", - ], - lambda p: p.name, - ) - - publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - ], - lambda p: p.name - ) - - publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__range=[1, 3]).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Sams", - "Prentice Hall", - "Morgan Kaufmann", - "Expensive Publisher", - ], - lambda p: p.name - ) - - publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__range=[1, 2]).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Sams", - "Prentice Hall", - "Morgan Kaufmann", - ], - lambda p: p.name - ) - - publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__in=[1, 3]).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Sams", - "Morgan Kaufmann", - "Expensive Publisher", - ], - lambda p: p.name, - ) - - publishers = Publisher.objects.annotate(num_books=Count("book")).filter(num_books__isnull=True) - self.assertEqual(len(publishers), 0) - - def test_annotation(self): - vals = Author.objects.filter(pk=1).aggregate(Count("friends__id")) - self.assertEqual(vals, {"friends__id__count": 2}) - - books = Book.objects.annotate(num_authors=Count("authors__name")).filter(num_authors__ge=2).order_by("pk") - self.assertQuerysetEqual( - books, [ - "The Definitive Guide to Django: Web Development Done Right", - "Artificial Intelligence: A Modern Approach", - ], - lambda b: b.name - ) - - authors = Author.objects.annotate(num_friends=Count("friends__id", distinct=True)).filter(num_friends=0).order_by("pk") - self.assertQuerysetEqual( - authors, [ - "Brad Dayley", - ], - lambda a: a.name - ) - - publishers = Publisher.objects.annotate(num_books=Count("book__id")).filter(num_books__gt=1).order_by("pk") - self.assertQuerysetEqual( - publishers, [ - "Apress", - "Prentice Hall", - ], - lambda p: p.name - ) - - publishers = Publisher.objects.filter(book__price__lt=Decimal("40.0")).annotate(num_books=Count("book__id")).filter(num_books__gt=1) - self.assertQuerysetEqual( - publishers, [ - "Apress", - ], - lambda p: p.name - ) - - books = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1) - self.assertQuerysetEqual( - books, [ - "Artificial Intelligence: A Modern Approach", - ], - lambda b: b.name - ) - - def test_more_aggregation(self): - a = Author.objects.get(name__contains='Norvig') - b = Book.objects.get(name__contains='Done Right') - b.authors.add(a) - b.save() - - vals = Book.objects.annotate(num_authors=Count("authors__id")).filter(authors__name__contains="Norvig", num_authors__gt=1).aggregate(Avg("rating")) - self.assertEqual(vals, {"rating__avg": 4.25}) - - def test_even_more_aggregate(self): - publishers = Publisher.objects.annotate(earliest_book=Min("book__pubdate")).exclude(earliest_book=None).order_by("earliest_book").values() - self.assertEqual( - list(publishers), [ - { - 'earliest_book': datetime.date(1991, 10, 15), - 'num_awards': 9, - 'id': 4, - 'name': u'Morgan Kaufmann' - }, - { - 'earliest_book': datetime.date(1995, 1, 15), - 'num_awards': 7, - 'id': 3, - 'name': u'Prentice Hall' - }, - { - 'earliest_book': datetime.date(2007, 12, 6), - 'num_awards': 3, - 'id': 1, - 'name': u'Apress' - }, - { - 'earliest_book': datetime.date(2008, 3, 3), - 'num_awards': 1, - 'id': 2, - 'name': u'Sams' - } - ] - ) - - vals = Store.objects.aggregate(Max("friday_night_closing"), Min("original_opening")) - self.assertEqual( - vals, - { - "friday_night_closing__max": datetime.time(23, 59, 59), - "original_opening__min": datetime.datetime(1945, 4, 25, 16, 24, 14), - } - ) - - def test_annotate_values_list(self): - books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("pk", "isbn", "mean_age") - self.assertEqual( - list(books), [ - (1, "159059725", 34.5), - ] - ) - - books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("isbn") - self.assertEqual( - list(books), [ - ('159059725',) - ] - ) - - books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("mean_age") - self.assertEqual( - list(books), [ - (34.5,) - ] - ) - - books = Book.objects.filter(pk=1).annotate(mean_age=Avg("authors__age")).values_list("mean_age", flat=True) - self.assertEqual(list(books), [34.5]) - - books = Book.objects.values_list("price").annotate(count=Count("price")).order_by("-count", "price") - self.assertEqual( - list(books), [ - (Decimal("29.69"), 2), - (Decimal('23.09'), 1), - (Decimal('30'), 1), - (Decimal('75'), 1), - (Decimal('82.8'), 1), - ] - ) diff --git a/parts/django/tests/modeltests/basic/__init__.py b/parts/django/tests/modeltests/basic/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/basic/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/basic/models.py b/parts/django/tests/modeltests/basic/models.py deleted file mode 100644 index 97552a9..0000000 --- a/parts/django/tests/modeltests/basic/models.py +++ /dev/null @@ -1,17 +0,0 @@ -# coding: utf-8 -""" -1. Bare-bones model - -This is a basic model with only two non-primary-key fields. -""" -from django.db import models, DEFAULT_DB_ALIAS - -class Article(models.Model): - headline = models.CharField(max_length=100, default='Default headline') - pub_date = models.DateTimeField() - - class Meta: - ordering = ('pub_date','headline') - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/basic/tests.py b/parts/django/tests/modeltests/basic/tests.py deleted file mode 100644 index bafe9a0..0000000 --- a/parts/django/tests/modeltests/basic/tests.py +++ /dev/null @@ -1,562 +0,0 @@ -from datetime import datetime -import re - -from django.conf import settings -from django.core.exceptions import ObjectDoesNotExist -from django.db import models, DEFAULT_DB_ALIAS, connection -from django.db.models.fields import FieldDoesNotExist -from django.test import TestCase - -from models import Article - - -class ModelTest(TestCase): - def assertRaisesErrorWithMessage(self, error, message, callable, *args, **kwargs): - self.assertRaises(error, callable, *args, **kwargs) - try: - callable(*args, **kwargs) - except error, e: - self.assertEqual(message, str(e)) - - def test_lookup(self): - # No articles are in the system yet. - self.assertQuerysetEqual(Article.objects.all(), []) - - # Create an Article. - a = Article( - id=None, - headline='Area man programs in Python', - pub_date=datetime(2005, 7, 28), - ) - - # Save it into the database. You have to call save() explicitly. - a.save() - - # Now it has an ID. - self.assertTrue(a.id != None) - - # Models have a pk property that is an alias for the primary key - # attribute (by default, the 'id' attribute). - self.assertEqual(a.pk, a.id) - - # Access database columns via Python attributes. - self.assertEqual(a.headline, 'Area man programs in Python') - self.assertEqual(a.pub_date, datetime(2005, 7, 28, 0, 0)) - - # Change values by changing the attributes, then calling save(). - a.headline = 'Area woman programs in Python' - a.save() - - # Article.objects.all() returns all the articles in the database. - self.assertQuerysetEqual(Article.objects.all(), - ['<Article: Area woman programs in Python>']) - - # Django provides a rich database lookup API. - self.assertEqual(Article.objects.get(id__exact=a.id), a) - self.assertEqual(Article.objects.get(headline__startswith='Area woman'), a) - self.assertEqual(Article.objects.get(pub_date__year=2005), a) - self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7), a) - self.assertEqual(Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28), a) - self.assertEqual(Article.objects.get(pub_date__week_day=5), a) - - # The "__exact" lookup type can be omitted, as a shortcut. - self.assertEqual(Article.objects.get(id=a.id), a) - self.assertEqual(Article.objects.get(headline='Area woman programs in Python'), a) - - self.assertQuerysetEqual( - Article.objects.filter(pub_date__year=2005), - ['<Article: Area woman programs in Python>'], - ) - self.assertQuerysetEqual( - Article.objects.filter(pub_date__year=2004), - [], - ) - self.assertQuerysetEqual( - Article.objects.filter(pub_date__year=2005, pub_date__month=7), - ['<Article: Area woman programs in Python>'], - ) - - self.assertQuerysetEqual( - Article.objects.filter(pub_date__week_day=5), - ['<Article: Area woman programs in Python>'], - ) - self.assertQuerysetEqual( - Article.objects.filter(pub_date__week_day=6), - [], - ) - - # Django raises an Article.DoesNotExist exception for get() if the - # parameters don't match any object. - self.assertRaisesErrorWithMessage( - ObjectDoesNotExist, - "Article matching query does not exist.", - Article.objects.get, - id__exact=2000, - ) - - self.assertRaisesErrorWithMessage( - ObjectDoesNotExist, - "Article matching query does not exist.", - Article.objects.get, - pub_date__year=2005, - pub_date__month=8, - ) - - self.assertRaisesErrorWithMessage( - ObjectDoesNotExist, - "Article matching query does not exist.", - Article.objects.get, - pub_date__week_day=6, - ) - - # Lookup by a primary key is the most common case, so Django - # provides a shortcut for primary-key exact lookups. - # The following is identical to articles.get(id=a.id). - self.assertEqual(Article.objects.get(pk=a.id), a) - - # pk can be used as a shortcut for the primary key name in any query. - self.assertQuerysetEqual(Article.objects.filter(pk__in=[a.id]), - ["<Article: Area woman programs in Python>"]) - - # Model instances of the same type and same ID are considered equal. - a = Article.objects.get(pk=a.id) - b = Article.objects.get(pk=a.id) - self.assertEqual(a, b) - - def test_object_creation(self): - # Create an Article. - a = Article( - id=None, - headline='Area man programs in Python', - pub_date=datetime(2005, 7, 28), - ) - - # Save it into the database. You have to call save() explicitly. - a.save() - - # You can initialize a model instance using positional arguments, - # which should match the field order as defined in the model. - a2 = Article(None, 'Second article', datetime(2005, 7, 29)) - a2.save() - - self.assertNotEqual(a2.id, a.id) - self.assertEqual(a2.headline, 'Second article') - self.assertEqual(a2.pub_date, datetime(2005, 7, 29, 0, 0)) - - # ...or, you can use keyword arguments. - a3 = Article( - id=None, - headline='Third article', - pub_date=datetime(2005, 7, 30), - ) - a3.save() - - self.assertNotEqual(a3.id, a.id) - self.assertNotEqual(a3.id, a2.id) - self.assertEqual(a3.headline, 'Third article') - self.assertEqual(a3.pub_date, datetime(2005, 7, 30, 0, 0)) - - # You can also mix and match position and keyword arguments, but - # be sure not to duplicate field information. - a4 = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31)) - a4.save() - self.assertEqual(a4.headline, 'Fourth article') - - # Don't use invalid keyword arguments. - self.assertRaisesErrorWithMessage( - TypeError, - "'foo' is an invalid keyword argument for this function", - Article, - id=None, - headline='Invalid', - pub_date=datetime(2005, 7, 31), - foo='bar', - ) - - # You can leave off the value for an AutoField when creating an - # object, because it'll get filled in automatically when you save(). - a5 = Article(headline='Article 6', pub_date=datetime(2005, 7, 31)) - a5.save() - self.assertEqual(a5.headline, 'Article 6') - - # If you leave off a field with "default" set, Django will use - # the default. - a6 = Article(pub_date=datetime(2005, 7, 31)) - a6.save() - self.assertEqual(a6.headline, u'Default headline') - - # For DateTimeFields, Django saves as much precision (in seconds) - # as you give it. - a7 = Article( - headline='Article 7', - pub_date=datetime(2005, 7, 31, 12, 30), - ) - a7.save() - self.assertEqual(Article.objects.get(id__exact=a7.id).pub_date, - datetime(2005, 7, 31, 12, 30)) - - a8 = Article( - headline='Article 8', - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - a8.save() - self.assertEqual(Article.objects.get(id__exact=a8.id).pub_date, - datetime(2005, 7, 31, 12, 30, 45)) - - # Saving an object again doesn't create a new object -- it just saves - # the old one. - current_id = a8.id - a8.save() - self.assertEqual(a8.id, current_id) - a8.headline = 'Updated article 8' - a8.save() - self.assertEqual(a8.id, current_id) - - # Check that != and == operators behave as expecte on instances - self.assertTrue(a7 != a8) - self.assertFalse(a7 == a8) - self.assertEqual(a8, Article.objects.get(id__exact=a8.id)) - - self.assertTrue(Article.objects.get(id__exact=a8.id) != Article.objects.get(id__exact=a7.id)) - self.assertFalse(Article.objects.get(id__exact=a8.id) == Article.objects.get(id__exact=a7.id)) - - # You can use 'in' to test for membership... - self.assertTrue(a8 in Article.objects.all()) - - # ... but there will often be more efficient ways if that is all you need: - self.assertTrue(Article.objects.filter(id=a8.id).exists()) - - # dates() returns a list of available dates of the given scope for - # the given field. - self.assertQuerysetEqual( - Article.objects.dates('pub_date', 'year'), - ["datetime.datetime(2005, 1, 1, 0, 0)"]) - self.assertQuerysetEqual( - Article.objects.dates('pub_date', 'month'), - ["datetime.datetime(2005, 7, 1, 0, 0)"]) - self.assertQuerysetEqual( - Article.objects.dates('pub_date', 'day'), - ["datetime.datetime(2005, 7, 28, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 31, 0, 0)"]) - self.assertQuerysetEqual( - Article.objects.dates('pub_date', 'day', order='ASC'), - ["datetime.datetime(2005, 7, 28, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 31, 0, 0)"]) - self.assertQuerysetEqual( - Article.objects.dates('pub_date', 'day', order='DESC'), - ["datetime.datetime(2005, 7, 31, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 28, 0, 0)"]) - - # dates() requires valid arguments. - self.assertRaisesErrorWithMessage( - TypeError, - "dates() takes at least 3 arguments (1 given)", - Article.objects.dates, - ) - - self.assertRaisesErrorWithMessage( - FieldDoesNotExist, - "Article has no field named 'invalid_field'", - Article.objects.dates, - "invalid_field", - "year", - ) - - self.assertRaisesErrorWithMessage( - AssertionError, - "'kind' must be one of 'year', 'month' or 'day'.", - Article.objects.dates, - "pub_date", - "bad_kind", - ) - - self.assertRaisesErrorWithMessage( - AssertionError, - "'order' must be either 'ASC' or 'DESC'.", - Article.objects.dates, - "pub_date", - "year", - order="bad order", - ) - - # Use iterator() with dates() to return a generator that lazily - # requests each result one at a time, to save memory. - dates = [] - for article in Article.objects.dates('pub_date', 'day', order='DESC').iterator(): - dates.append(article) - self.assertEqual(dates, [ - datetime(2005, 7, 31, 0, 0), - datetime(2005, 7, 30, 0, 0), - datetime(2005, 7, 29, 0, 0), - datetime(2005, 7, 28, 0, 0)]) - - # You can combine queries with & and |. - s1 = Article.objects.filter(id__exact=a.id) - s2 = Article.objects.filter(id__exact=a2.id) - self.assertQuerysetEqual(s1 | s2, - ["<Article: Area man programs in Python>", - "<Article: Second article>"]) - self.assertQuerysetEqual(s1 & s2, []) - - # You can get the number of objects like this: - self.assertEqual(len(Article.objects.filter(id__exact=a.id)), 1) - - # You can get items using index and slice notation. - self.assertEqual(Article.objects.all()[0], a) - self.assertQuerysetEqual(Article.objects.all()[1:3], - ["<Article: Second article>", "<Article: Third article>"]) - - s3 = Article.objects.filter(id__exact=a3.id) - self.assertQuerysetEqual((s1 | s2 | s3)[::2], - ["<Article: Area man programs in Python>", - "<Article: Third article>"]) - - # Slicing works with longs. - self.assertEqual(Article.objects.all()[0L], a) - self.assertQuerysetEqual(Article.objects.all()[1L:3L], - ["<Article: Second article>", "<Article: Third article>"]) - self.assertQuerysetEqual((s1 | s2 | s3)[::2L], - ["<Article: Area man programs in Python>", - "<Article: Third article>"]) - - # And can be mixed with ints. - self.assertQuerysetEqual(Article.objects.all()[1:3L], - ["<Article: Second article>", "<Article: Third article>"]) - - # Slices (without step) are lazy: - self.assertQuerysetEqual(Article.objects.all()[0:5].filter(), - ["<Article: Area man programs in Python>", - "<Article: Second article>", - "<Article: Third article>", - "<Article: Article 6>", - "<Article: Default headline>"]) - - # Slicing again works: - self.assertQuerysetEqual(Article.objects.all()[0:5][0:2], - ["<Article: Area man programs in Python>", - "<Article: Second article>"]) - self.assertQuerysetEqual(Article.objects.all()[0:5][:2], - ["<Article: Area man programs in Python>", - "<Article: Second article>"]) - self.assertQuerysetEqual(Article.objects.all()[0:5][4:], - ["<Article: Default headline>"]) - self.assertQuerysetEqual(Article.objects.all()[0:5][5:], []) - - # Some more tests! - self.assertQuerysetEqual(Article.objects.all()[2:][0:2], - ["<Article: Third article>", "<Article: Article 6>"]) - self.assertQuerysetEqual(Article.objects.all()[2:][:2], - ["<Article: Third article>", "<Article: Article 6>"]) - self.assertQuerysetEqual(Article.objects.all()[2:][2:3], - ["<Article: Default headline>"]) - - # Using an offset without a limit is also possible. - self.assertQuerysetEqual(Article.objects.all()[5:], - ["<Article: Fourth article>", - "<Article: Article 7>", - "<Article: Updated article 8>"]) - - # Also, once you have sliced you can't filter, re-order or combine - self.assertRaisesErrorWithMessage( - AssertionError, - "Cannot filter a query once a slice has been taken.", - Article.objects.all()[0:5].filter, - id=a.id, - ) - - self.assertRaisesErrorWithMessage( - AssertionError, - "Cannot reorder a query once a slice has been taken.", - Article.objects.all()[0:5].order_by, - 'id', - ) - - try: - Article.objects.all()[0:1] & Article.objects.all()[4:5] - self.fail('Should raise an AssertionError') - except AssertionError, e: - self.assertEqual(str(e), "Cannot combine queries once a slice has been taken.") - except Exception, e: - self.fail('Should raise an AssertionError, not %s' % e) - - # Negative slices are not supported, due to database constraints. - # (hint: inverting your ordering might do what you need). - try: - Article.objects.all()[-1] - self.fail('Should raise an AssertionError') - except AssertionError, e: - self.assertEqual(str(e), "Negative indexing is not supported.") - except Exception, e: - self.fail('Should raise an AssertionError, not %s' % e) - - error = None - try: - Article.objects.all()[0:-5] - except Exception, e: - error = e - self.assertTrue(isinstance(error, AssertionError)) - self.assertEqual(str(error), "Negative indexing is not supported.") - - # An Article instance doesn't have access to the "objects" attribute. - # That's only available on the class. - self.assertRaisesErrorWithMessage( - AttributeError, - "Manager isn't accessible via Article instances", - getattr, - a7, - "objects", - ) - - # Bulk delete test: How many objects before and after the delete? - self.assertQuerysetEqual(Article.objects.all(), - ["<Article: Area man programs in Python>", - "<Article: Second article>", - "<Article: Third article>", - "<Article: Article 6>", - "<Article: Default headline>", - "<Article: Fourth article>", - "<Article: Article 7>", - "<Article: Updated article 8>"]) - Article.objects.filter(id__lte=a4.id).delete() - self.assertQuerysetEqual(Article.objects.all(), - ["<Article: Article 6>", - "<Article: Default headline>", - "<Article: Article 7>", - "<Article: Updated article 8>"]) - - if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].startswith('django.db.backends.postgresql'): - def test_microsecond_precision(self): - # In PostgreSQL, microsecond-level precision is available. - a9 = Article( - headline='Article 9', - pub_date=datetime(2005, 7, 31, 12, 30, 45, 180), - ) - a9.save() - self.assertEqual(Article.objects.get(pk=a9.pk).pub_date, - datetime(2005, 7, 31, 12, 30, 45, 180)) - - if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.mysql': - def test_microsecond_precision_not_supported(self): - # In MySQL, microsecond-level precision isn't available. You'll lose - # microsecond-level precision once the data is saved. - a9 = Article( - headline='Article 9', - pub_date=datetime(2005, 7, 31, 12, 30, 45, 180), - ) - a9.save() - self.assertEqual(Article.objects.get(id__exact=a9.id).pub_date, - datetime(2005, 7, 31, 12, 30, 45)) - - def test_manually_specify_primary_key(self): - # You can manually specify the primary key when creating a new object. - a101 = Article( - id=101, - headline='Article 101', - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - a101.save() - a101 = Article.objects.get(pk=101) - self.assertEqual(a101.headline, u'Article 101') - - def test_create_method(self): - # You can create saved objects in a single step - a10 = Article.objects.create( - headline="Article 10", - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - self.assertEqual(Article.objects.get(headline="Article 10"), a10) - - def test_year_lookup_edge_case(self): - # Edge-case test: A year lookup should retrieve all objects in - # the given year, including Jan. 1 and Dec. 31. - a11 = Article.objects.create( - headline='Article 11', - pub_date=datetime(2008, 1, 1), - ) - a12 = Article.objects.create( - headline='Article 12', - pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999), - ) - self.assertQuerysetEqual(Article.objects.filter(pub_date__year=2008), - ["<Article: Article 11>", "<Article: Article 12>"]) - - def test_unicode_data(self): - # Unicode data works, too. - a = Article( - headline=u'\u6797\u539f \u3081\u3050\u307f', - pub_date=datetime(2005, 7, 28), - ) - a.save() - self.assertEqual(Article.objects.get(pk=a.id).headline, - u'\u6797\u539f \u3081\u3050\u307f') - - def test_hash_function(self): - # Model instances have a hash function, so they can be used in sets - # or as dictionary keys. Two models compare as equal if their primary - # keys are equal. - a10 = Article.objects.create( - headline="Article 10", - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - a11 = Article.objects.create( - headline='Article 11', - pub_date=datetime(2008, 1, 1), - ) - a12 = Article.objects.create( - headline='Article 12', - pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999), - ) - - s = set([a10, a11, a12]) - self.assertTrue(Article.objects.get(headline='Article 11') in s) - - def test_extra_method_select_argument_with_dashes_and_values(self): - # The 'select' argument to extra() supports names with dashes in - # them, as long as you use values(). - a10 = Article.objects.create( - headline="Article 10", - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - a11 = Article.objects.create( - headline='Article 11', - pub_date=datetime(2008, 1, 1), - ) - a12 = Article.objects.create( - headline='Article 12', - pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999), - ) - - dicts = Article.objects.filter( - pub_date__year=2008).extra( - select={'dashed-value': '1'} - ).values('headline', 'dashed-value') - self.assertEqual([sorted(d.items()) for d in dicts], - [[('dashed-value', 1), ('headline', u'Article 11')], [('dashed-value', 1), ('headline', u'Article 12')]]) - - def test_extra_method_select_argument_with_dashes(self): - # If you use 'select' with extra() and names containing dashes on a - # query that's *not* a values() query, those extra 'select' values - # will silently be ignored. - a10 = Article.objects.create( - headline="Article 10", - pub_date=datetime(2005, 7, 31, 12, 30, 45), - ) - a11 = Article.objects.create( - headline='Article 11', - pub_date=datetime(2008, 1, 1), - ) - a12 = Article.objects.create( - headline='Article 12', - pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999), - ) - - articles = Article.objects.filter( - pub_date__year=2008).extra( - select={'dashed-value': '1', 'undashedvalue': '2'}) - self.assertEqual(articles[0].undashedvalue, 2) diff --git a/parts/django/tests/modeltests/choices/__init__.py b/parts/django/tests/modeltests/choices/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/choices/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/choices/models.py b/parts/django/tests/modeltests/choices/models.py deleted file mode 100644 index 27316f5..0000000 --- a/parts/django/tests/modeltests/choices/models.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -21. Specifying 'choices' for a field - -Most fields take a ``choices`` parameter, which should be a tuple of tuples -specifying which are the valid values for that field. - -For each field that has ``choices``, a model instance gets a -``get_fieldname_display()`` method, where ``fieldname`` is the name of the -field. This method returns the "human-readable" value of the field. -""" - -from django.db import models - -GENDER_CHOICES = ( - ('M', 'Male'), - ('F', 'Female'), -) - -class Person(models.Model): - name = models.CharField(max_length=20) - gender = models.CharField(max_length=1, choices=GENDER_CHOICES) - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/choices/tests.py b/parts/django/tests/modeltests/choices/tests.py deleted file mode 100644 index 09023d8..0000000 --- a/parts/django/tests/modeltests/choices/tests.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.test import TestCase - -from models import Person - - -class ChoicesTests(TestCase): - def test_display(self): - a = Person.objects.create(name='Adrian', gender='M') - s = Person.objects.create(name='Sara', gender='F') - self.assertEqual(a.gender, 'M') - self.assertEqual(s.gender, 'F') - - self.assertEqual(a.get_gender_display(), 'Male') - self.assertEqual(s.get_gender_display(), 'Female') - - # If the value for the field doesn't correspond to a valid choice, - # the value itself is provided as a display value. - a.gender = '' - self.assertEqual(a.get_gender_display(), '') - - a.gender = 'U' - self.assertEqual(a.get_gender_display(), 'U') - diff --git a/parts/django/tests/modeltests/custom_columns/__init__.py b/parts/django/tests/modeltests/custom_columns/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/custom_columns/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/custom_columns/models.py b/parts/django/tests/modeltests/custom_columns/models.py deleted file mode 100644 index 651f8a6..0000000 --- a/parts/django/tests/modeltests/custom_columns/models.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -17. Custom column/table names - -If your database column name is different than your model attribute, use the -``db_column`` parameter. Note that you'll use the field's name, not its column -name, in API usage. - -If your database table name is different than your model name, use the -``db_table`` Meta attribute. This has no effect on the API used to -query the database. - -If you need to use a table name for a many-to-many relationship that differs -from the default generated name, use the ``db_table`` parameter on the -``ManyToManyField``. This has no effect on the API for querying the database. - -""" - -from django.db import models - -class Author(models.Model): - first_name = models.CharField(max_length=30, db_column='firstname') - last_name = models.CharField(max_length=30, db_column='last') - - def __unicode__(self): - return u'%s %s' % (self.first_name, self.last_name) - - class Meta: - db_table = 'my_author_table' - ordering = ('last_name','first_name') - -class Article(models.Model): - headline = models.CharField(max_length=100) - authors = models.ManyToManyField(Author, db_table='my_m2m_table') - - def __unicode__(self): - return self.headline - - class Meta: - ordering = ('headline',) - diff --git a/parts/django/tests/modeltests/custom_columns/tests.py b/parts/django/tests/modeltests/custom_columns/tests.py deleted file mode 100644 index f38f087..0000000 --- a/parts/django/tests/modeltests/custom_columns/tests.py +++ /dev/null @@ -1,71 +0,0 @@ -from django.core.exceptions import FieldError -from django.test import TestCase - -from models import Author, Article - - -class CustomColumnsTests(TestCase): - def test_db_column(self): - a1 = Author.objects.create(first_name="John", last_name="Smith") - a2 = Author.objects.create(first_name="Peter", last_name="Jones") - - art = Article.objects.create(headline="Django lets you build Web apps easily") - art.authors = [a1, a2] - - # Although the table and column names on Author have been set to custom - # values, nothing about using the Author model has changed... - - # Query the available authors - self.assertQuerysetEqual( - Author.objects.all(), [ - "Peter Jones", "John Smith", - ], - unicode - ) - self.assertQuerysetEqual( - Author.objects.filter(first_name__exact="John"), [ - "John Smith", - ], - unicode - ) - self.assertEqual( - Author.objects.get(first_name__exact="John"), - a1, - ) - - self.assertRaises(FieldError, - lambda: Author.objects.filter(firstname__exact="John") - ) - - a = Author.objects.get(last_name__exact="Smith") - a.first_name = "John" - a.last_name = "Smith" - - self.assertRaises(AttributeError, lambda: a.firstname) - self.assertRaises(AttributeError, lambda: a.last) - - # Although the Article table uses a custom m2m table, - # nothing about using the m2m relationship has changed... - - # Get all the authors for an article - self.assertQuerysetEqual( - art.authors.all(), [ - "Peter Jones", - "John Smith", - ], - unicode - ) - # Get the articles for an author - self.assertQuerysetEqual( - a.article_set.all(), [ - "Django lets you build Web apps easily", - ], - lambda a: a.headline - ) - # Query the authors across the m2m relation - self.assertQuerysetEqual( - art.authors.filter(last_name='Jones'), [ - "Peter Jones" - ], - unicode - ) diff --git a/parts/django/tests/modeltests/custom_managers/__init__.py b/parts/django/tests/modeltests/custom_managers/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/custom_managers/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/custom_managers/models.py b/parts/django/tests/modeltests/custom_managers/models.py deleted file mode 100644 index 1052552..0000000 --- a/parts/django/tests/modeltests/custom_managers/models.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -23. Giving models a custom manager - -You can use a custom ``Manager`` in a particular model by extending the base -``Manager`` class and instantiating your custom ``Manager`` in your model. - -There are two reasons you might want to customize a ``Manager``: to add extra -``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager`` -returns. -""" - -from django.db import models - -# An example of a custom manager called "objects". - -class PersonManager(models.Manager): - def get_fun_people(self): - return self.filter(fun=True) - -class Person(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - fun = models.BooleanField() - objects = PersonManager() - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) - -# An example of a custom manager that sets get_query_set(). - -class PublishedBookManager(models.Manager): - def get_query_set(self): - return super(PublishedBookManager, self).get_query_set().filter(is_published=True) - -class Book(models.Model): - title = models.CharField(max_length=50) - author = models.CharField(max_length=30) - is_published = models.BooleanField() - published_objects = PublishedBookManager() - authors = models.ManyToManyField(Person, related_name='books') - - def __unicode__(self): - return self.title - -# An example of providing multiple custom managers. - -class FastCarManager(models.Manager): - def get_query_set(self): - return super(FastCarManager, self).get_query_set().filter(top_speed__gt=150) - -class Car(models.Model): - name = models.CharField(max_length=10) - mileage = models.IntegerField() - top_speed = models.IntegerField(help_text="In miles per hour.") - cars = models.Manager() - fast_cars = FastCarManager() - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/custom_managers/tests.py b/parts/django/tests/modeltests/custom_managers/tests.py deleted file mode 100644 index 8721e9a..0000000 --- a/parts/django/tests/modeltests/custom_managers/tests.py +++ /dev/null @@ -1,71 +0,0 @@ -from django.test import TestCase - -from models import Person, Book, Car, PersonManager, PublishedBookManager - - -class CustomManagerTests(TestCase): - def test_manager(self): - p1 = Person.objects.create(first_name="Bugs", last_name="Bunny", fun=True) - p2 = Person.objects.create(first_name="Droopy", last_name="Dog", fun=False) - - self.assertQuerysetEqual( - Person.objects.get_fun_people(), [ - "Bugs Bunny" - ], - unicode - ) - # The RelatedManager used on the 'books' descriptor extends the default - # manager - self.assertTrue(isinstance(p2.books, PublishedBookManager)) - - b1 = Book.published_objects.create( - title="How to program", author="Rodney Dangerfield", is_published=True - ) - b2 = Book.published_objects.create( - title="How to be smart", author="Albert Einstein", is_published=False - ) - - # The default manager, "objects", doesn't exist, because a custom one - # was provided. - self.assertRaises(AttributeError, lambda: Book.objects) - - # The RelatedManager used on the 'authors' descriptor extends the - # default manager - self.assertTrue(isinstance(b2.authors, PersonManager)) - - self.assertQuerysetEqual( - Book.published_objects.all(), [ - "How to program", - ], - lambda b: b.title - ) - - c1 = Car.cars.create(name="Corvette", mileage=21, top_speed=180) - c2 = Car.cars.create(name="Neon", mileage=31, top_speed=100) - - self.assertQuerysetEqual( - Car.cars.order_by("name"), [ - "Corvette", - "Neon", - ], - lambda c: c.name - ) - - self.assertQuerysetEqual( - Car.fast_cars.all(), [ - "Corvette", - ], - lambda c: c.name - ) - - # Each model class gets a "_default_manager" attribute, which is a - # reference to the first manager defined in the class. In this case, - # it's "cars". - - self.assertQuerysetEqual( - Car._default_manager.order_by("name"), [ - "Corvette", - "Neon", - ], - lambda c: c.name - ) diff --git a/parts/django/tests/modeltests/custom_methods/__init__.py b/parts/django/tests/modeltests/custom_methods/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/custom_methods/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/custom_methods/models.py b/parts/django/tests/modeltests/custom_methods/models.py deleted file mode 100644 index 15150a6..0000000 --- a/parts/django/tests/modeltests/custom_methods/models.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -3. Giving models custom methods - -Any method you add to a model will be available to instances. -""" - -from django.db import models -import datetime - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateField() - - def __unicode__(self): - return self.headline - - def was_published_today(self): - return self.pub_date == datetime.date.today() - - def articles_from_same_day_1(self): - return Article.objects.filter(pub_date=self.pub_date).exclude(id=self.id) - - def articles_from_same_day_2(self): - """ - Verbose version of get_articles_from_same_day_1, which does a custom - database query for the sake of demonstration. - """ - from django.db import connection - cursor = connection.cursor() - cursor.execute(""" - SELECT id, headline, pub_date - FROM custom_methods_article - WHERE pub_date = %s - AND id != %s""", [connection.ops.value_to_db_date(self.pub_date), - self.id]) - return [self.__class__(*row) for row in cursor.fetchall()] diff --git a/parts/django/tests/modeltests/custom_methods/tests.py b/parts/django/tests/modeltests/custom_methods/tests.py deleted file mode 100644 index 90a7f0d..0000000 --- a/parts/django/tests/modeltests/custom_methods/tests.py +++ /dev/null @@ -1,42 +0,0 @@ -from datetime import date - -from django.test import TestCase - -from models import Article - - -class MethodsTests(TestCase): - def test_custom_methods(self): - a = Article.objects.create( - headline="Area man programs in Python", pub_date=date(2005, 7, 27) - ) - b = Article.objects.create( - headline="Beatles reunite", pub_date=date(2005, 7, 27) - ) - - self.assertFalse(a.was_published_today()) - self.assertQuerysetEqual( - a.articles_from_same_day_1(), [ - "Beatles reunite", - ], - lambda a: a.headline, - ) - self.assertQuerysetEqual( - a.articles_from_same_day_2(), [ - "Beatles reunite", - ], - lambda a: a.headline - ) - - self.assertQuerysetEqual( - b.articles_from_same_day_1(), [ - "Area man programs in Python", - ], - lambda a: a.headline, - ) - self.assertQuerysetEqual( - b.articles_from_same_day_2(), [ - "Area man programs in Python", - ], - lambda a: a.headline - ) diff --git a/parts/django/tests/modeltests/custom_pk/__init__.py b/parts/django/tests/modeltests/custom_pk/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/custom_pk/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/custom_pk/fields.py b/parts/django/tests/modeltests/custom_pk/fields.py deleted file mode 100644 index 2eeb80e..0000000 --- a/parts/django/tests/modeltests/custom_pk/fields.py +++ /dev/null @@ -1,55 +0,0 @@ -import random -import string - -from django.db import models - - -class MyWrapper(object): - def __init__(self, value): - self.value = value - - def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, self.value) - - def __unicode__(self): - return self.value - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.value == other.value - return self.value == other - -class MyAutoField(models.CharField): - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - kwargs['max_length'] = 10 - super(MyAutoField, self).__init__(*args, **kwargs) - - def pre_save(self, instance, add): - value = getattr(instance, self.attname, None) - if not value: - value = MyWrapper(''.join(random.sample(string.lowercase, 10))) - setattr(instance, self.attname, value) - return value - - def to_python(self, value): - if not value: - return - if not isinstance(value, MyWrapper): - value = MyWrapper(value) - return value - - def get_db_prep_save(self, value): - if not value: - return - if isinstance(value, MyWrapper): - return unicode(value) - return value - - def get_db_prep_value(self, value): - if not value: - return - if isinstance(value, MyWrapper): - return unicode(value) - return value diff --git a/parts/django/tests/modeltests/custom_pk/models.py b/parts/django/tests/modeltests/custom_pk/models.py deleted file mode 100644 index ff2f2ba..0000000 --- a/parts/django/tests/modeltests/custom_pk/models.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -""" -14. Using a custom primary key - -By default, Django adds an ``"id"`` field to each model. But you can override -this behavior by explicitly adding ``primary_key=True`` to a field. -""" - -from django.conf import settings -from django.db import models, transaction, IntegrityError, DEFAULT_DB_ALIAS - -from fields import MyAutoField - -class Employee(models.Model): - employee_code = models.IntegerField(primary_key=True, db_column = 'code') - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=20) - class Meta: - ordering = ('last_name', 'first_name') - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) - -class Business(models.Model): - name = models.CharField(max_length=20, primary_key=True) - employees = models.ManyToManyField(Employee) - class Meta: - verbose_name_plural = 'businesses' - - def __unicode__(self): - return self.name - -class Bar(models.Model): - id = MyAutoField(primary_key=True, db_index=True) - - def __unicode__(self): - return repr(self.pk) - - -class Foo(models.Model): - bar = models.ForeignKey(Bar) - diff --git a/parts/django/tests/modeltests/custom_pk/tests.py b/parts/django/tests/modeltests/custom_pk/tests.py deleted file mode 100644 index 6ef4bdd..0000000 --- a/parts/django/tests/modeltests/custom_pk/tests.py +++ /dev/null @@ -1,183 +0,0 @@ -# -*- coding: utf-8 -*- -from django.conf import settings -from django.db import DEFAULT_DB_ALIAS, transaction, IntegrityError -from django.test import TestCase - -from models import Employee, Business, Bar, Foo - - -class CustomPKTests(TestCase): - def test_custom_pk(self): - dan = Employee.objects.create( - employee_code=123, first_name="Dan", last_name="Jones" - ) - self.assertQuerysetEqual( - Employee.objects.all(), [ - "Dan Jones", - ], - unicode - ) - - fran = Employee.objects.create( - employee_code=456, first_name="Fran", last_name="Bones" - ) - self.assertQuerysetEqual( - Employee.objects.all(), [ - "Fran Bones", - "Dan Jones", - ], - unicode - ) - - self.assertEqual(Employee.objects.get(pk=123), dan) - self.assertEqual(Employee.objects.get(pk=456), fran) - - self.assertRaises(Employee.DoesNotExist, - lambda: Employee.objects.get(pk=42) - ) - - # Use the name of the primary key, rather than pk. - self.assertEqual(Employee.objects.get(employee_code=123), dan) - # pk can be used as a substitute for the primary key. - self.assertQuerysetEqual( - Employee.objects.filter(pk__in=[123, 456]), [ - "Fran Bones", - "Dan Jones", - ], - unicode - ) - # The primary key can be accessed via the pk property on the model. - e = Employee.objects.get(pk=123) - self.assertEqual(e.pk, 123) - # Or we can use the real attribute name for the primary key: - self.assertEqual(e.employee_code, 123) - - # Fran got married and changed her last name. - fran = Employee.objects.get(pk=456) - fran.last_name = "Jones" - fran.save() - - self.assertQuerysetEqual( - Employee.objects.filter(last_name="Jones"), [ - "Dan Jones", - "Fran Jones", - ], - unicode - ) - - emps = Employee.objects.in_bulk([123, 456]) - self.assertEqual(emps[123], dan) - - b = Business.objects.create(name="Sears") - b.employees.add(dan, fran) - self.assertQuerysetEqual( - b.employees.all(), [ - "Dan Jones", - "Fran Jones", - ], - unicode - ) - self.assertQuerysetEqual( - fran.business_set.all(), [ - "Sears", - ], - lambda b: b.name - ) - - self.assertEqual(Business.objects.in_bulk(["Sears"]), { - "Sears": b, - }) - - self.assertQuerysetEqual( - Business.objects.filter(name="Sears"), [ - "Sears" - ], - lambda b: b.name - ) - self.assertQuerysetEqual( - Business.objects.filter(pk="Sears"), [ - "Sears", - ], - lambda b: b.name - ) - - # Queries across tables, involving primary key - self.assertQuerysetEqual( - Employee.objects.filter(business__name="Sears"), [ - "Dan Jones", - "Fran Jones", - ], - unicode, - ) - self.assertQuerysetEqual( - Employee.objects.filter(business__pk="Sears"), [ - "Dan Jones", - "Fran Jones", - ], - unicode, - ) - - self.assertQuerysetEqual( - Business.objects.filter(employees__employee_code=123), [ - "Sears", - ], - lambda b: b.name - ) - self.assertQuerysetEqual( - Business.objects.filter(employees__pk=123), [ - "Sears", - ], - lambda b: b.name, - ) - - self.assertQuerysetEqual( - Business.objects.filter(employees__first_name__startswith="Fran"), [ - "Sears", - ], - lambda b: b.name - ) - - def test_unicode_pk(self): - # Primary key may be unicode string - bus = Business.objects.create(name=u'jaźń') - - def test_unique_pk(self): - # The primary key must also obviously be unique, so trying to create a - # new object with the same primary key will fail. - e = Employee.objects.create( - employee_code=123, first_name="Frank", last_name="Jones" - ) - sid = transaction.savepoint() - self.assertRaises(IntegrityError, - Employee.objects.create, employee_code=123, first_name="Fred", last_name="Jones" - ) - transaction.savepoint_rollback(sid) - - def test_custom_field_pk(self): - # Regression for #10785 -- Custom fields can be used for primary keys. - new_bar = Bar.objects.create() - new_foo = Foo.objects.create(bar=new_bar) - - # FIXME: This still doesn't work, but will require some changes in - # get_db_prep_lookup to fix it. - # f = Foo.objects.get(bar=new_bar.pk) - # self.assertEqual(f, new_foo) - # self.assertEqual(f.bar, new_bar) - - f = Foo.objects.get(bar=new_bar) - self.assertEqual(f, new_foo), - self.assertEqual(f.bar, new_bar) - - - # SQLite lets objects be saved with an empty primary key, even though an - # integer is expected. So we can't check for an error being raised in that - # case for SQLite. Remove it from the suite for this next bit. - if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.sqlite3': - def test_required_pk(self): - # The primary key must be specified, so an error is raised if you - # try to create an object without it. - sid = transaction.savepoint() - self.assertRaises(IntegrityError, - Employee.objects.create, first_name="Tom", last_name="Smith" - ) - transaction.savepoint_rollback(sid) diff --git a/parts/django/tests/modeltests/defer/__init__.py b/parts/django/tests/modeltests/defer/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/defer/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/defer/models.py b/parts/django/tests/modeltests/defer/models.py deleted file mode 100644 index 4fddd39..0000000 --- a/parts/django/tests/modeltests/defer/models.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -Tests for defer() and only(). -""" - -from django.db import models - - -class Secondary(models.Model): - first = models.CharField(max_length=50) - second = models.CharField(max_length=50) - -class Primary(models.Model): - name = models.CharField(max_length=50) - value = models.CharField(max_length=50) - related = models.ForeignKey(Secondary) - - def __unicode__(self): - return self.name - -class Child(Primary): - pass - -class BigChild(Primary): - other = models.CharField(max_length=50) diff --git a/parts/django/tests/modeltests/defer/tests.py b/parts/django/tests/modeltests/defer/tests.py deleted file mode 100644 index 5f6c53d..0000000 --- a/parts/django/tests/modeltests/defer/tests.py +++ /dev/null @@ -1,137 +0,0 @@ -from django.db.models.query_utils import DeferredAttribute -from django.test import TestCase - -from models import Secondary, Primary, Child, BigChild - - -class DeferTests(TestCase): - def assert_delayed(self, obj, num): - count = 0 - for field in obj._meta.fields: - if isinstance(obj.__class__.__dict__.get(field.attname), - DeferredAttribute): - count += 1 - self.assertEqual(count, num) - - def test_defer(self): - # To all outward appearances, instances with deferred fields look the - # same as normal instances when we examine attribute values. Therefore - # we test for the number of deferred fields on returned instances (by - # poking at the internals), as a way to observe what is going on. - - s1 = Secondary.objects.create(first="x1", second="y1") - p1 = Primary.objects.create(name="p1", value="xx", related=s1) - - qs = Primary.objects.all() - - self.assert_delayed(qs.defer("name")[0], 1) - self.assert_delayed(qs.only("name")[0], 2) - self.assert_delayed(qs.defer("related__first")[0], 0) - - obj = qs.select_related().only("related__first")[0] - self.assert_delayed(obj, 2) - - self.assertEqual(obj.related_id, s1.pk) - - self.assert_delayed(qs.defer("name").extra(select={"a": 1})[0], 1) - self.assert_delayed(qs.extra(select={"a": 1}).defer("name")[0], 1) - self.assert_delayed(qs.defer("name").defer("value")[0], 2) - self.assert_delayed(qs.only("name").only("value")[0], 2) - self.assert_delayed(qs.only("name").defer("value")[0], 2) - self.assert_delayed(qs.only("name", "value").defer("value")[0], 2) - self.assert_delayed(qs.defer("name").only("value")[0], 2) - - obj = qs.only()[0] - self.assert_delayed(qs.defer(None)[0], 0) - self.assert_delayed(qs.only("name").defer(None)[0], 0) - - # User values() won't defer anything (you get the full list of - # dictionaries back), but it still works. - self.assertEqual(qs.defer("name").values()[0], { - "id": p1.id, - "name": "p1", - "value": "xx", - "related_id": s1.id, - }) - self.assertEqual(qs.only("name").values()[0], { - "id": p1.id, - "name": "p1", - "value": "xx", - "related_id": s1.id, - }) - - # Using defer() and only() with get() is also valid. - self.assert_delayed(qs.defer("name").get(pk=p1.pk), 1) - self.assert_delayed(qs.only("name").get(pk=p1.pk), 2) - - # DOES THIS WORK? - self.assert_delayed(qs.only("name").select_related("related")[0], 1) - self.assert_delayed(qs.defer("related").select_related("related")[0], 0) - - # Saving models with deferred fields is possible (but inefficient, - # since every field has to be retrieved first). - obj = Primary.objects.defer("value").get(name="p1") - obj.name = "a new name" - obj.save() - self.assertQuerysetEqual( - Primary.objects.all(), [ - "a new name", - ], - lambda p: p.name - ) - - # Regression for #10572 - A subclass with no extra fields can defer - # fields from the base class - Child.objects.create(name="c1", value="foo", related=s1) - # You can defer a field on a baseclass when the subclass has no fields - obj = Child.objects.defer("value").get(name="c1") - self.assert_delayed(obj, 1) - self.assertEqual(obj.name, "c1") - self.assertEqual(obj.value, "foo") - obj.name = "c2" - obj.save() - - # You can retrive a single column on a base class with no fields - obj = Child.objects.only("name").get(name="c2") - self.assert_delayed(obj, 3) - self.assertEqual(obj.name, "c2") - self.assertEqual(obj.value, "foo") - obj.name = "cc" - obj.save() - - BigChild.objects.create(name="b1", value="foo", related=s1, other="bar") - # You can defer a field on a baseclass - obj = BigChild.objects.defer("value").get(name="b1") - self.assert_delayed(obj, 1) - self.assertEqual(obj.name, "b1") - self.assertEqual(obj.value, "foo") - self.assertEqual(obj.other, "bar") - obj.name = "b2" - obj.save() - - # You can defer a field on a subclass - obj = BigChild.objects.defer("other").get(name="b2") - self.assert_delayed(obj, 1) - self.assertEqual(obj.name, "b2") - self.assertEqual(obj.value, "foo") - self.assertEqual(obj.other, "bar") - obj.name = "b3" - obj.save() - - # You can retrieve a single field on a baseclass - obj = BigChild.objects.only("name").get(name="b3") - self.assert_delayed(obj, 4) - self.assertEqual(obj.name, "b3") - self.assertEqual(obj.value, "foo") - self.assertEqual(obj.other, "bar") - obj.name = "b4" - obj.save() - - # You can retrieve a single field on a baseclass - obj = BigChild.objects.only("other").get(name="b4") - self.assert_delayed(obj, 4) - self.assertEqual(obj.name, "b4") - self.assertEqual(obj.value, "foo") - self.assertEqual(obj.other, "bar") - obj.name = "bb" - obj.save() diff --git a/parts/django/tests/modeltests/delete/__init__.py b/parts/django/tests/modeltests/delete/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/parts/django/tests/modeltests/delete/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/parts/django/tests/modeltests/delete/models.py b/parts/django/tests/modeltests/delete/models.py deleted file mode 100644 index 9c81f6b..0000000 --- a/parts/django/tests/modeltests/delete/models.py +++ /dev/null @@ -1,42 +0,0 @@ -# coding: utf-8 -""" -Tests for some corner cases with deleting. -""" - -from django.db import models - -class DefaultRepr(object): - def __repr__(self): - return u"<%s: %s>" % (self.__class__.__name__, self.__dict__) - -class A(DefaultRepr, models.Model): - pass - -class B(DefaultRepr, models.Model): - a = models.ForeignKey(A) - -class C(DefaultRepr, models.Model): - b = models.ForeignKey(B) - -class D(DefaultRepr, models.Model): - c = models.ForeignKey(C) - a = models.ForeignKey(A) - -# Simplified, we have: -# A -# B -> A -# C -> B -# D -> C -# D -> A - -# So, we must delete Ds first of all, then Cs then Bs then As. -# However, if we start at As, we might find Bs first (in which -# case things will be nice), or find Ds first. - -# Some mutually dependent models, but nullable -class E(DefaultRepr, models.Model): - f = models.ForeignKey('F', null=True, related_name='e_rel') - -class F(DefaultRepr, models.Model): - e = models.ForeignKey(E, related_name='f_rel') - diff --git a/parts/django/tests/modeltests/delete/tests.py b/parts/django/tests/modeltests/delete/tests.py deleted file mode 100644 index 7927cce..0000000 --- a/parts/django/tests/modeltests/delete/tests.py +++ /dev/null @@ -1,135 +0,0 @@ -from django.db.models import sql -from django.db.models.loading import cache -from django.db.models.query import CollectedObjects -from django.db.models.query_utils import CyclicDependency -from django.test import TestCase - -from models import A, B, C, D, E, F - - -class DeleteTests(TestCase): - def clear_rel_obj_caches(self, *models): - for m in models: - if hasattr(m._meta, '_related_objects_cache'): - del m._meta._related_objects_cache - - def order_models(self, *models): - cache.app_models["delete"].keyOrder = models - - def setUp(self): - self.order_models("a", "b", "c", "d", "e", "f") - self.clear_rel_obj_caches(A, B, C, D, E, F) - - def tearDown(self): - self.order_models("a", "b", "c", "d", "e", "f") - self.clear_rel_obj_caches(A, B, C, D, E, F) - - def test_collected_objects(self): - g = CollectedObjects() - self.assertFalse(g.add("key1", 1, "item1", None)) - self.assertEqual(g["key1"], {1: "item1"}) - - self.assertFalse(g.add("key2", 1, "item1", "key1")) - self.assertFalse(g.add("key2", 2, "item2", "key1")) - - self.assertEqual(g["key2"], {1: "item1", 2: "item2"}) - - self.assertFalse(g.add("key3", 1, "item1", "key1")) - self.assertTrue(g.add("key3", 1, "item1", "key2")) - self.assertEqual(g.ordered_keys(), ["key3", "key2", "key1"]) - - self.assertTrue(g.add("key2", 1, "item1", "key3")) - self.assertRaises(CyclicDependency, g.ordered_keys) - - def test_delete(self): - ## Second, test the usage of CollectedObjects by Model.delete() - - # Due to the way that transactions work in the test harness, doing - # m.delete() here can work but fail in a real situation, since it may - # delete all objects, but not in the right order. So we manually check - # that the order of deletion is correct. - - # Also, it is possible that the order is correct 'accidentally', due - # solely to order of imports etc. To check this, we set the order that - # 'get_models()' will retrieve to a known 'nice' order, and then try - # again with a known 'tricky' order. Slightly naughty access to - # internals here :-) - - # If implementation changes, then the tests may need to be simplified: - # - remove the lines that set the .keyOrder and clear the related - # object caches - # - remove the second set of tests (with a2, b2 etc) - - a1 = A.objects.create() - b1 = B.objects.create(a=a1) - c1 = C.objects.create(b=b1) - d1 = D.objects.create(c=c1, a=a1) - - o = CollectedObjects() - a1._collect_sub_objects(o) - self.assertEqual(o.keys(), [D, C, B, A]) - a1.delete() - - # Same again with a known bad order - self.order_models("d", "c", "b", "a") - self.clear_rel_obj_caches(A, B, C, D) - - a2 = A.objects.create() - b2 = B.objects.create(a=a2) - c2 = C.objects.create(b=b2) - d2 = D.objects.create(c=c2, a=a2) - - o = CollectedObjects() - a2._collect_sub_objects(o) - self.assertEqual(o.keys(), [D, C, B, A]) - a2.delete() - - def test_collected_objects_null(self): - g = CollectedObjects() - self.assertFalse(g.add("key1", 1, "item1", None)) - self.assertFalse(g.add("key2", 1, "item1", "key1", nullable=True)) - self.assertTrue(g.add("key1", 1, "item1", "key2")) - self.assertEqual(g.ordered_keys(), ["key1", "key2"]) - - def test_delete_nullable(self): - e1 = E.objects.create() - f1 = F.objects.create(e=e1) - e1.f = f1 - e1.save() - - # Since E.f is nullable, we should delete F first (after nulling out - # the E.f field), then E. - - o = CollectedObjects() - e1._collect_sub_objects(o) - self.assertEqual(o.keys(), [F, E]) - - # temporarily replace the UpdateQuery class to verify that E.f is - # actually nulled out first - - logged = [] - class LoggingUpdateQuery(sql.UpdateQuery): - def clear_related(self, related_field, pk_list, using): - logged.append(related_field.name) - return super(LoggingUpdateQuery, self).clear_related(related_field, pk_list, using) - original = sql.UpdateQuery - sql.UpdateQuery = LoggingUpdateQuery - - e1.delete() - self.assertEqual(logged, ["f"]) - logged = [] - - e2 = E.objects.create() - f2 = F.objects.create(e=e2) - e2.f = f2 - e2.save() - - # Same deal as before, though we are starting from the other object. - o = CollectedObjects() - f2._collect_sub_objects(o) - self.assertEqual(o.keys(), [F, E]) - f2.delete() - self.assertEqual(logged, ["f"]) - logged = [] - - sql.UpdateQuery = original diff --git a/parts/django/tests/modeltests/empty/__init__.py b/parts/django/tests/modeltests/empty/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/empty/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/empty/models.py b/parts/django/tests/modeltests/empty/models.py deleted file mode 100644 index a6cdb0a..0000000 --- a/parts/django/tests/modeltests/empty/models.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -40. Empty model tests - -These test that things behave sensibly for the rare corner-case of a model with -no fields. -""" - -from django.db import models - - -class Empty(models.Model): - pass diff --git a/parts/django/tests/modeltests/empty/tests.py b/parts/django/tests/modeltests/empty/tests.py deleted file mode 100644 index 01fa1c5..0000000 --- a/parts/django/tests/modeltests/empty/tests.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.test import TestCase - -from models import Empty - - -class EmptyModelTests(TestCase): - def test_empty(self): - m = Empty() - self.assertEqual(m.id, None) - m.save() - m2 = Empty.objects.create() - self.assertEqual(len(Empty.objects.all()), 2) - self.assertTrue(m.id is not None) - existing = Empty(m.id) - existing.save() diff --git a/parts/django/tests/modeltests/expressions/__init__.py b/parts/django/tests/modeltests/expressions/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/expressions/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/expressions/models.py b/parts/django/tests/modeltests/expressions/models.py deleted file mode 100644 index b004408..0000000 --- a/parts/django/tests/modeltests/expressions/models.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Tests for F() query expression syntax. -""" - -from django.db import models - -class Employee(models.Model): - firstname = models.CharField(max_length=50) - lastname = models.CharField(max_length=50) - - def __unicode__(self): - return u'%s %s' % (self.firstname, self.lastname) - -class Company(models.Model): - name = models.CharField(max_length=100) - num_employees = models.PositiveIntegerField() - num_chairs = models.PositiveIntegerField() - ceo = models.ForeignKey( - Employee, - related_name='company_ceo_set') - point_of_contact = models.ForeignKey( - Employee, - related_name='company_point_of_contact_set', - null=True) - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/expressions/tests.py b/parts/django/tests/modeltests/expressions/tests.py deleted file mode 100644 index 0a136ae..0000000 --- a/parts/django/tests/modeltests/expressions/tests.py +++ /dev/null @@ -1,218 +0,0 @@ -from django.core.exceptions import FieldError -from django.db.models import F -from django.test import TestCase - -from models import Company, Employee - - -class ExpressionsTests(TestCase): - def test_filter(self): - Company.objects.create( - name="Example Inc.", num_employees=2300, num_chairs=5, - ceo=Employee.objects.create(firstname="Joe", lastname="Smith") - ) - Company.objects.create( - name="Foobar Ltd.", num_employees=3, num_chairs=4, - ceo=Employee.objects.create(firstname="Frank", lastname="Meyer") - ) - Company.objects.create( - name="Test GmbH", num_employees=32, num_chairs=1, - ceo=Employee.objects.create(firstname="Max", lastname="Mustermann") - ) - - company_query = Company.objects.values( - "name", "num_employees", "num_chairs" - ).order_by( - "name", "num_employees", "num_chairs" - ) - - # We can filter for companies where the number of employees is greater - # than the number of chairs. - self.assertQuerysetEqual( - company_query.filter(num_employees__gt=F("num_chairs")), [ - { - "num_chairs": 5, - "name": "Example Inc.", - "num_employees": 2300, - }, - { - "num_chairs": 1, - "name": "Test GmbH", - "num_employees": 32 - }, - ], - lambda o: o - ) - - # We can set one field to have the value of another field - # Make sure we have enough chairs - company_query.update(num_chairs=F("num_employees")) - self.assertQuerysetEqual( - company_query, [ - { - "num_chairs": 2300, - "name": "Example Inc.", - "num_employees": 2300 - }, - { - "num_chairs": 3, - "name": "Foobar Ltd.", - "num_employees": 3 - }, - { - "num_chairs": 32, - "name": "Test GmbH", - "num_employees": 32 - } - ], - lambda o: o - ) - - # We can perform arithmetic operations in expressions - # Make sure we have 2 spare chairs - company_query.update(num_chairs=F("num_employees")+2) - self.assertQuerysetEqual( - company_query, [ - { - 'num_chairs': 2302, - 'name': u'Example Inc.', - 'num_employees': 2300 - }, - { - 'num_chairs': 5, - 'name': u'Foobar Ltd.', - 'num_employees': 3 - }, - { - 'num_chairs': 34, - 'name': u'Test GmbH', - 'num_employees': 32 - } - ], - lambda o: o, - ) - - # Law of order of operations is followed - company_query.update( - num_chairs=F('num_employees') + 2 * F('num_employees') - ) - self.assertQuerysetEqual( - company_query, [ - { - 'num_chairs': 6900, - 'name': u'Example Inc.', - 'num_employees': 2300 - }, - { - 'num_chairs': 9, - 'name': u'Foobar Ltd.', - 'num_employees': 3 - }, - { - 'num_chairs': 96, - 'name': u'Test GmbH', - 'num_employees': 32 - } - ], - lambda o: o, - ) - - # Law of order of operations can be overridden by parentheses - company_query.update( - num_chairs=((F('num_employees') + 2) * F('num_employees')) - ) - self.assertQuerysetEqual( - company_query, [ - { - 'num_chairs': 5294600, - 'name': u'Example Inc.', - 'num_employees': 2300 - }, - { - 'num_chairs': 15, - 'name': u'Foobar Ltd.', - 'num_employees': 3 - }, - { - 'num_chairs': 1088, - 'name': u'Test GmbH', - 'num_employees': 32 - } - ], - lambda o: o, - ) - - # The relation of a foreign key can become copied over to an other - # foreign key. - self.assertEqual( - Company.objects.update(point_of_contact=F('ceo')), - 3 - ) - self.assertQuerysetEqual( - Company.objects.all(), [ - "Joe Smith", - "Frank Meyer", - "Max Mustermann", - ], - lambda c: unicode(c.point_of_contact), - ) - - c = Company.objects.all()[0] - c.point_of_contact = Employee.objects.create(firstname="Guido", lastname="van Rossum") - c.save() - - # F Expressions can also span joins - self.assertQuerysetEqual( - Company.objects.filter(ceo__firstname=F("point_of_contact__firstname")), [ - "Foobar Ltd.", - "Test GmbH", - ], - lambda c: c.name - ) - - Company.objects.exclude( - ceo__firstname=F("point_of_contact__firstname") - ).update(name="foo") - self.assertEqual( - Company.objects.exclude( - ceo__firstname=F('point_of_contact__firstname') - ).get().name, - "foo", - ) - - self.assertRaises(FieldError, - lambda: Company.objects.exclude( - ceo__firstname=F('point_of_contact__firstname') - ).update(name=F('point_of_contact__lastname')) - ) - - # F expressions can be used to update attributes on single objects - test_gmbh = Company.objects.get(name="Test GmbH") - self.assertEqual(test_gmbh.num_employees, 32) - test_gmbh.num_employees = F("num_employees") + 4 - test_gmbh.save() - test_gmbh = Company.objects.get(pk=test_gmbh.pk) - self.assertEqual(test_gmbh.num_employees, 36) - - # F expressions cannot be used to update attributes which are foreign - # keys, or attributes which involve joins. - test_gmbh.point_of_contact = None - test_gmbh.save() - self.assertTrue(test_gmbh.point_of_contact is None) - def test(): - test_gmbh.point_of_contact = F("ceo") - self.assertRaises(ValueError, test) - - test_gmbh.point_of_contact = test_gmbh.ceo - test_gmbh.save() - test_gmbh.name = F("ceo__last_name") - self.assertRaises(FieldError, test_gmbh.save) - - # F expressions cannot be used to update attributes on objects which do - # not yet exist in the database - acme = Company( - name="The Acme Widget Co.", num_employees=12, num_chairs=5, - ceo=test_gmbh.ceo - ) - acme.num_employees = F("num_employees") + 16 - self.assertRaises(TypeError, acme.save) diff --git a/parts/django/tests/modeltests/field_defaults/__init__.py b/parts/django/tests/modeltests/field_defaults/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/field_defaults/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/field_defaults/models.py b/parts/django/tests/modeltests/field_defaults/models.py deleted file mode 100644 index 0dd1f72..0000000 --- a/parts/django/tests/modeltests/field_defaults/models.py +++ /dev/null @@ -1,21 +0,0 @@ -# coding: utf-8 -""" -32. Callable defaults - -You can pass callable objects as the ``default`` parameter to a field. When -the object is created without an explicit value passed in, Django will call -the method to determine the default value. - -This example uses ``datetime.datetime.now`` as the default for the ``pub_date`` -field. -""" - -from django.db import models -from datetime import datetime - -class Article(models.Model): - headline = models.CharField(max_length=100, default='Default headline') - pub_date = models.DateTimeField(default=datetime.now) - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/field_defaults/tests.py b/parts/django/tests/modeltests/field_defaults/tests.py deleted file mode 100644 index a23f644..0000000 --- a/parts/django/tests/modeltests/field_defaults/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -from datetime import datetime - -from django.test import TestCase - -from models import Article - - -class DefaultTests(TestCase): - def test_field_defaults(self): - a = Article() - now = datetime.now() - a.save() - - self.assertTrue(isinstance(a.id, (int, long))) - self.assertEqual(a.headline, "Default headline") - self.assertTrue((now - a.pub_date).seconds < 5) diff --git a/parts/django/tests/modeltests/field_subclassing/__init__.py b/parts/django/tests/modeltests/field_subclassing/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/field_subclassing/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/field_subclassing/fields.py b/parts/django/tests/modeltests/field_subclassing/fields.py deleted file mode 100644 index 8675b31..0000000 --- a/parts/django/tests/modeltests/field_subclassing/fields.py +++ /dev/null @@ -1,74 +0,0 @@ -from django.core.exceptions import FieldError -from django.db import models -from django.utils import simplejson as json -from django.utils.encoding import force_unicode - - -class Small(object): - """ - A simple class to show that non-trivial Python objects can be used as - attributes. - """ - def __init__(self, first, second): - self.first, self.second = first, second - - def __unicode__(self): - return u'%s%s' % (force_unicode(self.first), force_unicode(self.second)) - - def __str__(self): - return unicode(self).encode('utf-8') - -class SmallField(models.Field): - """ - Turns the "Small" class into a Django field. Because of the similarities - with normal character fields and the fact that Small.__unicode__ does - something sensible, we don't need to implement a lot here. - """ - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - kwargs['max_length'] = 2 - super(SmallField, self).__init__(*args, **kwargs) - - def get_internal_type(self): - return 'CharField' - - def to_python(self, value): - if isinstance(value, Small): - return value - return Small(value[0], value[1]) - - def get_db_prep_save(self, value): - return unicode(value) - - def get_prep_lookup(self, lookup_type, value): - if lookup_type == 'exact': - return force_unicode(value) - if lookup_type == 'in': - return [force_unicode(v) for v in value] - if lookup_type == 'isnull': - return [] - raise TypeError('Invalid lookup type: %r' % lookup_type) - -class SmallerField(SmallField): - pass - - -class JSONField(models.TextField): - __metaclass__ = models.SubfieldBase - - description = ("JSONField automatically serializes and desializes values to " - "and from JSON.") - - def to_python(self, value): - if not value: - return None - - if isinstance(value, basestring): - value = json.loads(value) - return value - - def get_db_prep_save(self, value): - if value is None: - return None - return json.dumps(value) diff --git a/parts/django/tests/modeltests/field_subclassing/models.py b/parts/django/tests/modeltests/field_subclassing/models.py deleted file mode 100644 index b0d8336..0000000 --- a/parts/django/tests/modeltests/field_subclassing/models.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -Tests for field subclassing. -""" - -from django.db import models -from django.utils.encoding import force_unicode - -from fields import Small, SmallField, SmallerField, JSONField - - -class MyModel(models.Model): - name = models.CharField(max_length=10) - data = SmallField('small field') - - def __unicode__(self): - return force_unicode(self.name) - -class OtherModel(models.Model): - data = SmallerField() - -class DataModel(models.Model): - data = JSONField() diff --git a/parts/django/tests/modeltests/field_subclassing/tests.py b/parts/django/tests/modeltests/field_subclassing/tests.py deleted file mode 100644 index 25f5160..0000000 --- a/parts/django/tests/modeltests/field_subclassing/tests.py +++ /dev/null @@ -1,81 +0,0 @@ -from django.core import serializers -from django.test import TestCase - -from fields import Small -from models import DataModel, MyModel, OtherModel - - -class CustomField(TestCase): - def test_defer(self): - d = DataModel.objects.create(data=[1, 2, 3]) - - self.assertTrue(isinstance(d.data, list)) - - d = DataModel.objects.get(pk=d.pk) - self.assertTrue(isinstance(d.data, list)) - self.assertEqual(d.data, [1, 2, 3]) - - d = DataModel.objects.defer("data").get(pk=d.pk) - d.save() - - d = DataModel.objects.get(pk=d.pk) - self.assertTrue(isinstance(d.data, list)) - self.assertEqual(d.data, [1, 2, 3]) - - def test_custom_field(self): - # Creating a model with custom fields is done as per normal. - s = Small(1, 2) - self.assertEqual(str(s), "12") - - m = MyModel.objects.create(name="m", data=s) - # Custom fields still have normal field's attributes. - self.assertEqual(m._meta.get_field("data").verbose_name, "small field") - - # The m.data attribute has been initialised correctly. It's a Small - # object. - self.assertEqual((m.data.first, m.data.second), (1, 2)) - - # The data loads back from the database correctly and 'data' has the - # right type. - m1 = MyModel.objects.get(pk=m.pk) - self.assertTrue(isinstance(m1.data, Small)) - self.assertEqual(str(m1.data), "12") - - # We can do normal filtering on the custom field (and will get an error - # when we use a lookup type that does not make sense). - s1 = Small(1, 3) - s2 = Small("a", "b") - self.assertQuerysetEqual( - MyModel.objects.filter(data__in=[s, s1, s2]), [ - "m", - ], - lambda m: m.name, - ) - self.assertRaises(TypeError, lambda: MyModel.objects.filter(data__lt=s)) - - # Serialization works, too. - stream = serializers.serialize("json", MyModel.objects.all()) - self.assertEqual(stream, '[{"pk": 1, "model": "field_subclassing.mymodel", "fields": {"data": "12", "name": "m"}}]') - - obj = list(serializers.deserialize("json", stream))[0] - self.assertEqual(obj.object, m) - - # Test retrieving custom field data - m.delete() - - m1 = MyModel.objects.create(name="1", data=Small(1, 2)) - m2 = MyModel.objects.create(name="2", data=Small(2, 3)) - - self.assertQuerysetEqual( - MyModel.objects.all(), [ - "12", - "23", - ], - lambda m: str(m.data) - ) - - def test_field_subclassing(self): - o = OtherModel.objects.create(data=Small("a", "b")) - o = OtherModel.objects.get() - self.assertEqual(o.data.first, "a") - self.assertEqual(o.data.second, "b") diff --git a/parts/django/tests/modeltests/files/__init__.py b/parts/django/tests/modeltests/files/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/parts/django/tests/modeltests/files/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/parts/django/tests/modeltests/files/models.py b/parts/django/tests/modeltests/files/models.py deleted file mode 100644 index f798f74..0000000 --- a/parts/django/tests/modeltests/files/models.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -42. Storing files according to a custom storage system - -``FileField`` and its variations can take a ``storage`` argument to specify how -and where files should be stored. -""" - -import random -import tempfile - -from django.db import models -from django.core.files.base import ContentFile -from django.core.files.storage import FileSystemStorage - - -temp_storage_location = tempfile.mkdtemp() -temp_storage = FileSystemStorage(location=temp_storage_location) - -# Write out a file to be used as default content -temp_storage.save('tests/default.txt', ContentFile('default content')) - -class Storage(models.Model): - def custom_upload_to(self, filename): - return 'foo' - - def random_upload_to(self, filename): - # This returns a different result each time, - # to make sure it only gets called once. - return '%s/%s' % (random.randint(100, 999), filename) - - normal = models.FileField(storage=temp_storage, upload_to='tests') - custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) - random = models.FileField(storage=temp_storage, upload_to=random_upload_to) - default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') diff --git a/parts/django/tests/modeltests/files/tests.py b/parts/django/tests/modeltests/files/tests.py deleted file mode 100644 index 025fcc5..0000000 --- a/parts/django/tests/modeltests/files/tests.py +++ /dev/null @@ -1,100 +0,0 @@ -import shutil - -from django.core.cache import cache -from django.core.files.base import ContentFile -from django.core.files.uploadedfile import SimpleUploadedFile -from django.test import TestCase - -from models import Storage, temp_storage, temp_storage_location - - -class FileTests(TestCase): - def tearDown(self): - shutil.rmtree(temp_storage_location) - - def test_files(self): - # Attempting to access a FileField from the class raises a descriptive - # error - self.assertRaises(AttributeError, lambda: Storage.normal) - - # An object without a file has limited functionality. - obj1 = Storage() - self.assertEqual(obj1.normal.name, "") - self.assertRaises(ValueError, lambda: obj1.normal.size) - - # Saving a file enables full functionality. - obj1.normal.save("django_test.txt", ContentFile("content")) - self.assertEqual(obj1.normal.name, "tests/django_test.txt") - self.assertEqual(obj1.normal.size, 7) - self.assertEqual(obj1.normal.read(), "content") - - # File objects can be assigned to FileField attributes, but shouldn't - # get committed until the model it's attached to is saved. - obj1.normal = SimpleUploadedFile("assignment.txt", "content") - dirs, files = temp_storage.listdir("tests") - self.assertEqual(dirs, []) - self.assertEqual(sorted(files), ["default.txt", "django_test.txt"]) - - obj1.save() - dirs, files = temp_storage.listdir("tests") - self.assertEqual( - sorted(files), ["assignment.txt", "default.txt", "django_test.txt"] - ) - - # Files can be read in a little at a time, if necessary. - obj1.normal.open() - self.assertEqual(obj1.normal.read(3), "con") - self.assertEqual(obj1.normal.read(), "tent") - self.assertEqual(list(obj1.normal.chunks(chunk_size=2)), ["co", "nt", "en", "t"]) - - # Save another file with the same name. - obj2 = Storage() - obj2.normal.save("django_test.txt", ContentFile("more content")) - self.assertEqual(obj2.normal.name, "tests/django_test_1.txt") - self.assertEqual(obj2.normal.size, 12) - - # Push the objects into the cache to make sure they pickle properly - cache.set("obj1", obj1) - cache.set("obj2", obj2) - self.assertEqual(cache.get("obj2").normal.name, "tests/django_test_1.txt") - - # Deleting an object deletes the file it uses, if there are no other - # objects still using that file. - obj2.delete() - obj2.normal.save("django_test.txt", ContentFile("more content")) - self.assertEqual(obj2.normal.name, "tests/django_test_1.txt") - - # Multiple files with the same name get _N appended to them. - objs = [Storage() for i in range(3)] - for o in objs: - o.normal.save("multiple_files.txt", ContentFile("Same Content")) - self.assertEqual( - [o.normal.name for o in objs], - ["tests/multiple_files.txt", "tests/multiple_files_1.txt", "tests/multiple_files_2.txt"] - ) - for o in objs: - o.delete() - - # Default values allow an object to access a single file. - obj3 = Storage.objects.create() - self.assertEqual(obj3.default.name, "tests/default.txt") - self.assertEqual(obj3.default.read(), "default content") - - # But it shouldn't be deleted, even if there are no more objects using - # it. - obj3.delete() - obj3 = Storage() - self.assertEqual(obj3.default.read(), "default content") - - # Verify the fix for #5655, making sure the directory is only - # determined once. - obj4 = Storage() - obj4.random.save("random_file", ContentFile("random content")) - self.assertTrue(obj4.random.name.endswith("/random_file")) - - # Clean up the temporary files and dir. - obj1.normal.delete() - obj2.normal.delete() - obj3.default.delete() - obj4.random.delete() - diff --git a/parts/django/tests/modeltests/fixtures/__init__.py b/parts/django/tests/modeltests/fixtures/__init__.py deleted file mode 100644 index 139597f..0000000 --- a/parts/django/tests/modeltests/fixtures/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_1.default.json b/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_1.default.json deleted file mode 100644 index 9bb39e4..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_1.default.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "pk": "6", - "model": "fixtures.article", - "fields": { - "headline": "Who needs more than one database?", - "pub_date": "2006-06-16 14:00:00" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_2.default.json.gz b/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_2.default.json.gz Binary files differdeleted file mode 100644 index 80e4ba1..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_2.default.json.gz +++ /dev/null diff --git a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_3.nosuchdb.json b/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_3.nosuchdb.json deleted file mode 100644 index 3da326b..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/db_fixture_3.nosuchdb.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "pk": "8", - "model": "fixtures.article", - "fields": { - "headline": "There is no spoon.", - "pub_date": "2006-06-16 14:00:00" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture1.json b/parts/django/tests/modeltests/fixtures/fixtures/fixture1.json deleted file mode 100644 index 332feae..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture1.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "pk": 1, - "model": "sites.site", - "fields": { - "domain": "example.com", - "name": "example.com" - } - }, - { - "pk": "2", - "model": "fixtures.article", - "fields": { - "headline": "Poker has no place on ESPN", - "pub_date": "2006-06-16 12:00:00" - } - }, - { - "pk": "3", - "model": "fixtures.article", - "fields": { - "headline": "Time to reform copyright", - "pub_date": "2006-06-16 13:00:00" - } - }, - { - "pk": 1, - "model": "fixtures.category", - "fields": { - "description": "Latest news stories", - "title": "News Stories" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture2.json b/parts/django/tests/modeltests/fixtures/fixtures/fixture2.json deleted file mode 100644 index 01b40d7..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture2.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "pk": "3", - "model": "fixtures.article", - "fields": { - "headline": "Copyright is fine the way it is", - "pub_date": "2006-06-16 14:00:00" - } - }, - { - "pk": "4", - "model": "fixtures.article", - "fields": { - "headline": "Django conquers world!", - "pub_date": "2006-06-16 15:00:00" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture2.xml b/parts/django/tests/modeltests/fixtures/fixtures/fixture2.xml deleted file mode 100644 index 9ced781..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture2.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="2" model="fixtures.article"> - <field type="CharField" name="headline">Poker on TV is great!</field> - <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> - </object> - <object pk="5" model="fixtures.article"> - <field type="CharField" name="headline">XML identified as leading cause of cancer</field> - <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> - </object> -</django-objects>
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture3.xml b/parts/django/tests/modeltests/fixtures/fixtures/fixture3.xml deleted file mode 100644 index 9ced781..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture3.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="2" model="fixtures.article"> - <field type="CharField" name="headline">Poker on TV is great!</field> - <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> - </object> - <object pk="5" model="fixtures.article"> - <field type="CharField" name="headline">XML identified as leading cause of cancer</field> - <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> - </object> -</django-objects>
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture4.json.zip b/parts/django/tests/modeltests/fixtures/fixtures/fixture4.json.zip Binary files differdeleted file mode 100644 index 270cccb..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture4.json.zip +++ /dev/null diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.gz b/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.gz Binary files differdeleted file mode 100644 index bb6baca..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.gz +++ /dev/null diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.zip b/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.zip Binary files differdeleted file mode 100644 index 9380cef..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture5.json.zip +++ /dev/null diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture6.json b/parts/django/tests/modeltests/fixtures/fixtures/fixture6.json deleted file mode 100644 index 60e4733..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture6.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "pk": "1", - "model": "fixtures.tag", - "fields": { - "name": "copyright", - "tagged_type": ["fixtures", "article"], - "tagged_id": "3" - } - }, - { - "pk": "2", - "model": "fixtures.tag", - "fields": { - "name": "law", - "tagged_type": ["fixtures", "article"], - "tagged_id": "3" - } - }, - { - "pk": "1", - "model": "fixtures.person", - "fields": { - "name": "Django Reinhardt" - } - }, - { - "pk": "2", - "model": "fixtures.person", - "fields": { - "name": "Stephane Grappelli" - } - }, - { - "pk": "3", - "model": "fixtures.person", - "fields": { - "name": "Prince" - } - } -] diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture7.xml b/parts/django/tests/modeltests/fixtures/fixtures/fixture7.xml deleted file mode 100644 index 547cba1..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture7.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="2" model="fixtures.tag"> - <field type="CharField" name="name">legal</field> - <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> - <natural>fixtures</natural> - <natural>article</natural> - </field> - <field type="PositiveIntegerField" name="tagged_id">3</field> - </object> - <object pk="3" model="fixtures.tag"> - <field type="CharField" name="name">django</field> - <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> - <natural>fixtures</natural> - <natural>article</natural> - </field> - <field type="PositiveIntegerField" name="tagged_id">4</field> - </object> - <object pk="4" model="fixtures.tag"> - <field type="CharField" name="name">world domination</field> - <field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"> - <natural>fixtures</natural> - <natural>article</natural> - </field> - <field type="PositiveIntegerField" name="tagged_id">4</field> - </object> -</django-objects> diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture8.json b/parts/django/tests/modeltests/fixtures/fixtures/fixture8.json deleted file mode 100644 index bc113aa..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture8.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "pk": "1", - "model": "fixtures.visa", - "fields": { - "person": ["Django Reinhardt"], - "permissions": [ - ["add_user", "auth", "user"], - ["change_user", "auth", "user"], - ["delete_user", "auth", "user"] - ] - } - }, - { - "pk": "2", - "model": "fixtures.visa", - "fields": { - "person": ["Stephane Grappelli"], - "permissions": [ - ["add_user", "auth", "user"] - ] - } - }, - { - "pk": "3", - "model": "fixtures.visa", - "fields": { - "person": ["Prince"], - "permissions": [] - } - } -] diff --git a/parts/django/tests/modeltests/fixtures/fixtures/fixture9.xml b/parts/django/tests/modeltests/fixtures/fixtures/fixture9.xml deleted file mode 100644 index 100f63d..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/fixture9.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="2" model="fixtures.visa"> - <field type="CharField" name="person"> - <natural>Stephane Grappelli</natural> - </field> - <field to="auth.permission" name="permissions" rel="ManyToManyRel"> - <object> - <natural>add_user</natural> - <natural>auth</natural> - <natural>user</natural> - </object> - <object> - <natural>delete_user</natural> - <natural>auth</natural> - <natural>user</natural> - </object> - </field> - </object> - <object pk="3" model="fixtures.person"> - <field type="CharField" name="name"> - <natural>Artist formerly known as "Prince"</natural> - </field> - </object> - <object pk="3" model="fixtures.visa"> - <field type="CharField" name="person"> - <natural>Artist formerly known as "Prince"</natural> - </field> - <field to="auth.permission" name="permissions" rel="ManyToManyRel"> - <object> - <natural>change_user</natural> - <natural>auth</natural> - <natural>user</natural> - </object> - </field> - </object> - <object pk="1" model="fixtures.book"> - <field type="CharField" name="name">Music for all ages</field> - <field to="fixtures.person" name="authors" rel="ManyToManyRel"> - <object> - <natural>Django Reinhardt</natural> - </object> - <object> - <natural>Artist formerly known as "Prince"</natural> - </object> - </field> - </object> -</django-objects> diff --git a/parts/django/tests/modeltests/fixtures/fixtures/initial_data.json b/parts/django/tests/modeltests/fixtures/fixtures/initial_data.json deleted file mode 100644 index 477d781..0000000 --- a/parts/django/tests/modeltests/fixtures/fixtures/initial_data.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "pk": "1", - "model": "fixtures.article", - "fields": { - "headline": "Python program becomes self aware", - "pub_date": "2006-06-16 11:00:00" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/fixtures/models.py b/parts/django/tests/modeltests/fixtures/models.py deleted file mode 100644 index 216a8e2..0000000 --- a/parts/django/tests/modeltests/fixtures/models.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -37. Fixtures. - -Fixtures are a way of loading data into the database in bulk. Fixure data -can be stored in any serializable format (including JSON and XML). Fixtures -are identified by name, and are stored in either a directory named 'fixtures' -in the application directory, on in one of the directories named in the -``FIXTURE_DIRS`` setting. -""" - -from django.contrib.auth.models import Permission -from django.contrib.contenttypes import generic -from django.contrib.contenttypes.models import ContentType -from django.db import models, DEFAULT_DB_ALIAS -from django.conf import settings - - -class Category(models.Model): - title = models.CharField(max_length=100) - description = models.TextField() - - def __unicode__(self): - return self.title - - class Meta: - ordering = ('title',) - -class Article(models.Model): - headline = models.CharField(max_length=100, default='Default headline') - pub_date = models.DateTimeField() - - def __unicode__(self): - return self.headline - - class Meta: - ordering = ('-pub_date', 'headline') - -class Blog(models.Model): - name = models.CharField(max_length=100) - featured = models.ForeignKey(Article, related_name='fixtures_featured_set') - articles = models.ManyToManyField(Article, blank=True, - related_name='fixtures_articles_set') - - def __unicode__(self): - return self.name - - -class Tag(models.Model): - name = models.CharField(max_length=100) - tagged_type = models.ForeignKey(ContentType, related_name="fixtures_tag_set") - tagged_id = models.PositiveIntegerField(default=0) - tagged = generic.GenericForeignKey(ct_field='tagged_type', - fk_field='tagged_id') - - def __unicode__(self): - return '<%s: %s> tagged "%s"' % (self.tagged.__class__.__name__, - self.tagged, self.name) - -class PersonManager(models.Manager): - def get_by_natural_key(self, name): - return self.get(name=name) - -class Person(models.Model): - objects = PersonManager() - name = models.CharField(max_length=100) - def __unicode__(self): - return self.name - - class Meta: - ordering = ('name',) - - def natural_key(self): - return (self.name,) - -class Visa(models.Model): - person = models.ForeignKey(Person) - permissions = models.ManyToManyField(Permission, blank=True) - - def __unicode__(self): - return '%s %s' % (self.person.name, - ', '.join(p.name for p in self.permissions.all())) - -class Book(models.Model): - name = models.CharField(max_length=100) - authors = models.ManyToManyField(Person) - - def __unicode__(self): - return '%s by %s' % (self.name, - ' and '.join(a.name for a in self.authors.all())) - - class Meta: - ordering = ('name',) diff --git a/parts/django/tests/modeltests/fixtures/tests.py b/parts/django/tests/modeltests/fixtures/tests.py deleted file mode 100644 index 4facc6d..0000000 --- a/parts/django/tests/modeltests/fixtures/tests.py +++ /dev/null @@ -1,277 +0,0 @@ -import StringIO -import sys - -from django.test import TestCase, TransactionTestCase -from django.conf import settings -from django.core import management -from django.db import DEFAULT_DB_ALIAS - -from models import Article, Blog, Book, Category, Person, Tag, Visa - -class TestCaseFixtureLoadingTests(TestCase): - fixtures = ['fixture1.json', 'fixture2.json'] - - def testClassFixtures(self): - "Check that test case has installed 4 fixture objects" - self.assertEqual(Article.objects.count(), 4) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Django conquers world!>', - '<Article: Copyright is fine the way it is>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) - -class FixtureLoadingTests(TestCase): - - def _dumpdata_assert(self, args, output, format='json', natural_keys=False): - new_io = StringIO.StringIO() - management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io, 'use_natural_keys':natural_keys}) - command_output = new_io.getvalue().strip() - self.assertEqual(command_output, output) - - def test_initial_data(self): - # Syncdb introduces 1 initial data object from initial_data.json. - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Python program becomes self aware>' - ]) - - def test_loading_and_dumping(self): - new_io = StringIO.StringIO() - - # Load fixture 1. Single JSON file, with two objects. - management.call_command('loaddata', 'fixture1.json', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Time to reform copyright>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) - - # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Try just dumping the contents of fixtures.Category - self._dumpdata_assert(['fixtures.Category'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]') - - # ...and just fixtures.Article - self._dumpdata_assert(['fixtures.Article'], '[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # ...and both - self._dumpdata_assert(['fixtures.Category', 'fixtures.Article'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Specify a specific model twice - self._dumpdata_assert(['fixtures.Article', 'fixtures.Article'], '[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Specify a dump that specifies Article both explicitly and implicitly - self._dumpdata_assert(['fixtures.Article', 'fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Same again, but specify in the reverse order - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Specify one model from one application, and an entire other application. - self._dumpdata_assert(['fixtures.Category', 'sites'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}]') - - # Load fixture 2. JSON file imported by default. Overwrites some existing objects - management.call_command('loaddata', 'fixture2.json', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Django conquers world!>', - '<Article: Copyright is fine the way it is>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) - - # Load fixture 3, XML format. - management.call_command('loaddata', 'fixture3.xml', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: XML identified as leading cause of cancer>', - '<Article: Django conquers world!>', - '<Article: Copyright is fine the way it is>', - '<Article: Poker on TV is great!>', - '<Article: Python program becomes self aware>' - ]) - - # Load fixture 6, JSON file with dynamic ContentType fields. Testing ManyToOne. - management.call_command('loaddata', 'fixture6.json', verbosity=0, commit=False) - self.assertQuerysetEqual(Tag.objects.all(), [ - '<Tag: <Article: Copyright is fine the way it is> tagged "copyright">', - '<Tag: <Article: Copyright is fine the way it is> tagged "law">' - ]) - - # Load fixture 7, XML file with dynamic ContentType fields. Testing ManyToOne. - management.call_command('loaddata', 'fixture7.xml', verbosity=0, commit=False) - self.assertQuerysetEqual(Tag.objects.all(), [ - '<Tag: <Article: Copyright is fine the way it is> tagged "copyright">', - '<Tag: <Article: Copyright is fine the way it is> tagged "legal">', - '<Tag: <Article: Django conquers world!> tagged "django">', - '<Tag: <Article: Django conquers world!> tagged "world domination">' - ]) - - # Load fixture 8, JSON file with dynamic Permission fields. Testing ManyToMany. - management.call_command('loaddata', 'fixture8.json', verbosity=0, commit=False) - self.assertQuerysetEqual(Visa.objects.all(), [ - '<Visa: Django Reinhardt Can add user, Can change user, Can delete user>', - '<Visa: Stephane Grappelli Can add user>', - '<Visa: Prince >' - ]) - - # Load fixture 9, XML file with dynamic Permission fields. Testing ManyToMany. - management.call_command('loaddata', 'fixture9.xml', verbosity=0, commit=False) - self.assertQuerysetEqual(Visa.objects.all(), [ - '<Visa: Django Reinhardt Can add user, Can change user, Can delete user>', - '<Visa: Stephane Grappelli Can add user, Can delete user>', - '<Visa: Artist formerly known as "Prince" Can change user>' - ]) - - self.assertQuerysetEqual(Book.objects.all(), [ - '<Book: Music for all ages by Artist formerly known as "Prince" and Django Reinhardt>' - ]) - - # Load a fixture that doesn't exist - management.call_command('loaddata', 'unknown.json', verbosity=0, commit=False) - - # object list is unaffected - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: XML identified as leading cause of cancer>', - '<Article: Django conquers world!>', - '<Article: Copyright is fine the way it is>', - '<Article: Poker on TV is great!>', - '<Article: Python program becomes self aware>' - ]) - - # By default, you get raw keys on dumpdata - self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}]') - - # But you can get natural keys if you ask for them and they are available - self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_keys=True) - - # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16 16:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16 15:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16 14:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_keys=True) - - # Dump the current contents of the database as an XML fixture - self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="5" model="fixtures.article"><field type="CharField" name="headline">XML identified as leading cause of cancer</field><field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field></object><object pk="4" model="fixtures.article"><field type="CharField" name="headline">Django conquers world!</field><field type="DateTimeField" name="pub_date">2006-06-16 15:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Copyright is fine the way it is</field><field type="DateTimeField" name="pub_date">2006-06-16 14:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker on TV is great!</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">legal</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="3" model="fixtures.tag"><field type="CharField" name="name">django</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="4" model="fixtures.tag"><field type="CharField" name="name">world domination</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Artist formerly known as "Prince"</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="1" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Django Reinhardt</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="2" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Stephane Grappelli</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="3" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Artist formerly known as "Prince"</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="1" model="fixtures.book"><field type="CharField" name="name">Music for all ages</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"><object><natural>Artist formerly known as "Prince"</natural></object><object><natural>Django Reinhardt</natural></object></field></object></django-objects>""", format='xml', natural_keys=True) - - def test_compress_format_loading(self): - # Load fixture 4 (compressed), using format specification - management.call_command('loaddata', 'fixture4.json', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Django pets kitten>', - '<Article: Python program becomes self aware>' - ]) - - def test_compressed_specified_loading(self): - # Load fixture 5 (compressed), using format *and* compression specification - management.call_command('loaddata', 'fixture5.json.zip', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: WoW subscribers now outnumber readers>', - '<Article: Python program becomes self aware>' - ]) - - def test_compressed_loading(self): - # Load fixture 5 (compressed), only compression specification - management.call_command('loaddata', 'fixture5.zip', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: WoW subscribers now outnumber readers>', - '<Article: Python program becomes self aware>' - ]) - - def test_ambiguous_compressed_fixture(self): - # The name "fixture5" is ambigous, so loading it will raise an error - new_io = StringIO.StringIO() - management.call_command('loaddata', 'fixture5', verbosity=0, stderr=new_io, commit=False) - output = new_io.getvalue().strip().split('\n') - self.assertEqual(len(output), 1) - self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture5'")) - - def test_db_loading(self): - # Load db fixtures 1 and 2. These will load using the 'default' database identifier implicitly - management.call_command('loaddata', 'db_fixture_1', verbosity=0, commit=False) - management.call_command('loaddata', 'db_fixture_2', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Who needs more than one database?>', - '<Article: Who needs to use compressed data?>', - '<Article: Python program becomes self aware>' - ]) - - def test_loading_using(self): - # Load db fixtures 1 and 2. These will load using the 'default' database identifier explicitly - management.call_command('loaddata', 'db_fixture_1', verbosity=0, using='default', commit=False) - management.call_command('loaddata', 'db_fixture_2', verbosity=0, using='default', commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Who needs more than one database?>', - '<Article: Who needs to use compressed data?>', - '<Article: Python program becomes self aware>' - ]) - - def test_unmatched_identifier_loading(self): - # Try to load db fixture 3. This won't load because the database identifier doesn't match - management.call_command('loaddata', 'db_fixture_3', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Python program becomes self aware>' - ]) - - management.call_command('loaddata', 'db_fixture_3', verbosity=0, using='default', commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Python program becomes self aware>' - ]) - - def test_output_formats(self): - # Load back in fixture 1, we need the articles from it - management.call_command('loaddata', 'fixture1', verbosity=0, commit=False) - - # Try to load fixture 6 using format discovery - management.call_command('loaddata', 'fixture6', verbosity=0, commit=False) - self.assertQuerysetEqual(Tag.objects.all(), [ - '<Tag: <Article: Time to reform copyright> tagged "copyright">', - '<Tag: <Article: Time to reform copyright> tagged "law">' - ]) - - # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}]', natural_keys=True) - - # Dump the current contents of the database as an XML fixture - self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16 13:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16 12:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object></django-objects>""", format='xml', natural_keys=True) - -if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql': - class FixtureTransactionTests(TransactionTestCase): - def _dumpdata_assert(self, args, output, format='json'): - new_io = StringIO.StringIO() - management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io}) - command_output = new_io.getvalue().strip() - self.assertEqual(command_output, output) - - def test_format_discovery(self): - # Load fixture 1 again, using format discovery - management.call_command('loaddata', 'fixture1', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Time to reform copyright>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) - - # Try to load fixture 2 using format discovery; this will fail - # because there are two fixture2's in the fixtures directory - new_io = StringIO.StringIO() - management.call_command('loaddata', 'fixture2', verbosity=0, stderr=new_io) - output = new_io.getvalue().strip().split('\n') - self.assertEqual(len(output), 1) - self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture2'")) - - # object list is unaffected - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Time to reform copyright>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) - - # Dump the current contents of the database as a JSON fixture - self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]') - - # Load fixture 4 (compressed), using format discovery - management.call_command('loaddata', 'fixture4', verbosity=0, commit=False) - self.assertQuerysetEqual(Article.objects.all(), [ - '<Article: Django pets kitten>', - '<Article: Time to reform copyright>', - '<Article: Poker has no place on ESPN>', - '<Article: Python program becomes self aware>' - ]) diff --git a/parts/django/tests/modeltests/fixtures_model_package/__init__.py b/parts/django/tests/modeltests/fixtures_model_package/__init__.py deleted file mode 100644 index 139597f..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture1.json b/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture1.json deleted file mode 100644 index 7684d84..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture1.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "pk": "2", - "model": "fixtures_model_package.article", - "fields": { - "headline": "Poker has no place on ESPN", - "pub_date": "2006-06-16 12:00:00" - } - }, - { - "pk": "3", - "model": "fixtures_model_package.article", - "fields": { - "headline": "Time to reform copyright", - "pub_date": "2006-06-16 13:00:00" - } - } -] diff --git a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.json b/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.json deleted file mode 100644 index 4997627..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "pk": "3", - "model": "fixtures_model_package.article", - "fields": { - "headline": "Copyright is fine the way it is", - "pub_date": "2006-06-16 14:00:00" - } - }, - { - "pk": "4", - "model": "fixtures_model_package.article", - "fields": { - "headline": "Django conquers world!", - "pub_date": "2006-06-16 15:00:00" - } - } -] diff --git a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.xml b/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.xml deleted file mode 100644 index 55337cf..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/fixtures/fixture2.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="2" model="fixtures_model_package.article"> - <field type="CharField" name="headline">Poker on TV is great!</field> - <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> - </object> - <object pk="5" model="fixtures_model_package.article"> - <field type="CharField" name="headline">XML identified as leading cause of cancer</field> - <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> - </object> -</django-objects> diff --git a/parts/django/tests/modeltests/fixtures_model_package/fixtures/initial_data.json b/parts/django/tests/modeltests/fixtures_model_package/fixtures/initial_data.json deleted file mode 100644 index 66cb5d7..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/fixtures/initial_data.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "pk": "1", - "model": "fixtures_model_package.article", - "fields": { - "headline": "Python program becomes self aware", - "pub_date": "2006-06-16 11:00:00" - } - } -] diff --git a/parts/django/tests/modeltests/fixtures_model_package/models/__init__.py b/parts/django/tests/modeltests/fixtures_model_package/models/__init__.py deleted file mode 100644 index c0450b2..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/models/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.db import models -from django.conf import settings - -class Article(models.Model): - headline = models.CharField(max_length=100, default='Default headline') - pub_date = models.DateTimeField() - - def __unicode__(self): - return self.headline - - class Meta: - app_label = 'fixtures_model_package' - ordering = ('-pub_date', 'headline') - diff --git a/parts/django/tests/modeltests/fixtures_model_package/tests.py b/parts/django/tests/modeltests/fixtures_model_package/tests.py deleted file mode 100644 index 1fae5ee..0000000 --- a/parts/django/tests/modeltests/fixtures_model_package/tests.py +++ /dev/null @@ -1,71 +0,0 @@ -from django.core import management -from django.test import TestCase - -from models import Article - - -class SampleTestCase(TestCase): - fixtures = ['fixture1.json', 'fixture2.json'] - - def testClassFixtures(self): - "Test cases can load fixture objects into models defined in packages" - self.assertEqual(Article.objects.count(), 4) - self.assertQuerysetEqual( - Article.objects.all(),[ - "Django conquers world!", - "Copyright is fine the way it is", - "Poker has no place on ESPN", - "Python program becomes self aware" - ], - lambda a: a.headline - ) - - -class FixtureTestCase(TestCase): - def test_initial_data(self): - "Fixtures can load initial data into models defined in packages" - #Syncdb introduces 1 initial data object from initial_data.json - self.assertQuerysetEqual( - Article.objects.all(), [ - "Python program becomes self aware" - ], - lambda a: a.headline - ) - - def test_loaddata(self): - "Fixtures can load data into models defined in packages" - # Load fixture 1. Single JSON file, with two objects - management.call_command("loaddata", "fixture1.json", verbosity=0, commit=False) - self.assertQuerysetEqual( - Article.objects.all(), [ - "Time to reform copyright", - "Poker has no place on ESPN", - "Python program becomes self aware", - ], - lambda a: a.headline, - ) - - # Load fixture 2. JSON file imported by default. Overwrites some - # existing objects - management.call_command("loaddata", "fixture2.json", verbosity=0, commit=False) - self.assertQuerysetEqual( - Article.objects.all(), [ - "Django conquers world!", - "Copyright is fine the way it is", - "Poker has no place on ESPN", - "Python program becomes self aware", - ], - lambda a: a.headline, - ) - - # Load a fixture that doesn't exist - management.call_command("loaddata", "unknown.json", verbosity=0, commit=False) - self.assertQuerysetEqual( - Article.objects.all(), [ - "Django conquers world!", - "Copyright is fine the way it is", - "Poker has no place on ESPN", - "Python program becomes self aware", - ], - lambda a: a.headline, - ) diff --git a/parts/django/tests/modeltests/force_insert_update/__init__.py b/parts/django/tests/modeltests/force_insert_update/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/force_insert_update/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/force_insert_update/models.py b/parts/django/tests/modeltests/force_insert_update/models.py deleted file mode 100644 index 9516be7..0000000 --- a/parts/django/tests/modeltests/force_insert_update/models.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -Tests for forcing insert and update queries (instead of Django's normal -automatic behaviour). -""" -from django.db import models, transaction, IntegrityError - -class Counter(models.Model): - name = models.CharField(max_length = 10) - value = models.IntegerField() - -class WithCustomPK(models.Model): - name = models.IntegerField(primary_key=True) - value = models.IntegerField() diff --git a/parts/django/tests/modeltests/force_insert_update/tests.py b/parts/django/tests/modeltests/force_insert_update/tests.py deleted file mode 100644 index bd3eb7d..0000000 --- a/parts/django/tests/modeltests/force_insert_update/tests.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.db import transaction, IntegrityError, DatabaseError -from django.test import TestCase - -from models import Counter, WithCustomPK - - -class ForceTests(TestCase): - def test_force_update(self): - c = Counter.objects.create(name="one", value=1) - # The normal case - - c.value = 2 - c.save() - # Same thing, via an update - c.value = 3 - c.save(force_update=True) - - # Won't work because force_update and force_insert are mutually - # exclusive - c.value = 4 - self.assertRaises(ValueError, c.save, force_insert=True, force_update=True) - - # Try to update something that doesn't have a primary key in the first - # place. - c1 = Counter(name="two", value=2) - self.assertRaises(ValueError, c1.save, force_update=True) - c1.save(force_insert=True) - - # Won't work because we can't insert a pk of the same value. - sid = transaction.savepoint() - c.value = 5 - self.assertRaises(IntegrityError, c.save, force_insert=True) - transaction.savepoint_rollback(sid) - - # Trying to update should still fail, even with manual primary keys, if - # the data isn't in the database already. - obj = WithCustomPK(name=1, value=1) - self.assertRaises(DatabaseError, obj.save, force_update=True) diff --git a/parts/django/tests/modeltests/generic_relations/__init__.py b/parts/django/tests/modeltests/generic_relations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/generic_relations/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/generic_relations/models.py b/parts/django/tests/modeltests/generic_relations/models.py deleted file mode 100644 index 18b77a3..0000000 --- a/parts/django/tests/modeltests/generic_relations/models.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -34. Generic relations - -Generic relations let an object have a foreign key to any object through a -content-type/object-id field. A ``GenericForeignKey`` field can point to any -object, be it animal, vegetable, or mineral. - -The canonical example is tags (although this example implementation is *far* -from complete). -""" - -from django.contrib.contenttypes import generic -from django.contrib.contenttypes.models import ContentType -from django.db import models - - -class TaggedItem(models.Model): - """A tag on an item.""" - tag = models.SlugField() - content_type = models.ForeignKey(ContentType) - object_id = models.PositiveIntegerField() - - content_object = generic.GenericForeignKey() - - class Meta: - ordering = ["tag", "content_type__name"] - - def __unicode__(self): - return self.tag - -class ValuableTaggedItem(TaggedItem): - value = models.PositiveIntegerField() - -class Comparison(models.Model): - """ - A model that tests having multiple GenericForeignKeys - """ - comparative = models.CharField(max_length=50) - - content_type1 = models.ForeignKey(ContentType, related_name="comparative1_set") - object_id1 = models.PositiveIntegerField() - - content_type2 = models.ForeignKey(ContentType, related_name="comparative2_set") - object_id2 = models.PositiveIntegerField() - - first_obj = generic.GenericForeignKey(ct_field="content_type1", fk_field="object_id1") - other_obj = generic.GenericForeignKey(ct_field="content_type2", fk_field="object_id2") - - def __unicode__(self): - return u"%s is %s than %s" % (self.first_obj, self.comparative, self.other_obj) - -class Animal(models.Model): - common_name = models.CharField(max_length=150) - latin_name = models.CharField(max_length=150) - - tags = generic.GenericRelation(TaggedItem) - comparisons = generic.GenericRelation(Comparison, - object_id_field="object_id1", - content_type_field="content_type1") - - def __unicode__(self): - return self.common_name - -class Vegetable(models.Model): - name = models.CharField(max_length=150) - is_yucky = models.BooleanField(default=True) - - tags = generic.GenericRelation(TaggedItem) - - def __unicode__(self): - return self.name - -class Mineral(models.Model): - name = models.CharField(max_length=150) - hardness = models.PositiveSmallIntegerField() - - # note the lack of an explicit GenericRelation here... - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/generic_relations/tests.py b/parts/django/tests/modeltests/generic_relations/tests.py deleted file mode 100644 index 3d25301..0000000 --- a/parts/django/tests/modeltests/generic_relations/tests.py +++ /dev/null @@ -1,223 +0,0 @@ -from django.contrib.contenttypes.generic import generic_inlineformset_factory -from django.contrib.contenttypes.models import ContentType -from django.test import TestCase - -from models import (TaggedItem, ValuableTaggedItem, Comparison, Animal, - Vegetable, Mineral) - - -class GenericRelationsTests(TestCase): - def test_generic_relations(self): - # Create the world in 7 lines of code... - lion = Animal.objects.create(common_name="Lion", latin_name="Panthera leo") - platypus = Animal.objects.create( - common_name="Platypus", latin_name="Ornithorhynchus anatinus" - ) - eggplant = Vegetable.objects.create(name="Eggplant", is_yucky=True) - bacon = Vegetable.objects.create(name="Bacon", is_yucky=False) - quartz = Mineral.objects.create(name="Quartz", hardness=7) - - # Objects with declared GenericRelations can be tagged directly -- the - # API mimics the many-to-many API. - bacon.tags.create(tag="fatty") - bacon.tags.create(tag="salty") - lion.tags.create(tag="yellow") - lion.tags.create(tag="hairy") - platypus.tags.create(tag="fatty") - self.assertQuerysetEqual(lion.tags.all(), [ - "<TaggedItem: hairy>", - "<TaggedItem: yellow>" - ]) - self.assertQuerysetEqual(bacon.tags.all(), [ - "<TaggedItem: fatty>", - "<TaggedItem: salty>" - ]) - - # You can easily access the content object like a foreign key. - t = TaggedItem.objects.get(tag="salty") - self.assertEqual(t.content_object, bacon) - - # Recall that the Mineral class doesn't have an explicit GenericRelation - # defined. That's OK, because you can create TaggedItems explicitly. - tag1 = TaggedItem.objects.create(content_object=quartz, tag="shiny") - tag2 = TaggedItem.objects.create(content_object=quartz, tag="clearish") - - # However, excluding GenericRelations means your lookups have to be a - # bit more explicit. - ctype = ContentType.objects.get_for_model(quartz) - q = TaggedItem.objects.filter( - content_type__pk=ctype.id, object_id=quartz.id - ) - self.assertQuerysetEqual(q, [ - "<TaggedItem: clearish>", - "<TaggedItem: shiny>" - ]) - - # You can set a generic foreign key in the way you'd expect. - tag1.content_object = platypus - tag1.save() - self.assertQuerysetEqual(platypus.tags.all(), [ - "<TaggedItem: fatty>", - "<TaggedItem: shiny>" - ]) - q = TaggedItem.objects.filter( - content_type__pk=ctype.id, object_id=quartz.id - ) - self.assertQuerysetEqual(q, ["<TaggedItem: clearish>"]) - - # Queries across generic relations respect the content types. Even - # though there are two TaggedItems with a tag of "fatty", this query - # only pulls out the one with the content type related to Animals. - self.assertQuerysetEqual(Animal.objects.order_by('common_name'), [ - "<Animal: Lion>", - "<Animal: Platypus>" - ]) - self.assertQuerysetEqual(Animal.objects.filter(tags__tag='fatty'), [ - "<Animal: Platypus>" - ]) - self.assertQuerysetEqual(Animal.objects.exclude(tags__tag='fatty'), [ - "<Animal: Lion>" - ]) - - # If you delete an object with an explicit Generic relation, the related - # objects are deleted when the source object is deleted. - # Original list of tags: - comp_func = lambda obj: ( - obj.tag, obj.content_type.model_class(), obj.object_id - ) - - self.assertQuerysetEqual(TaggedItem.objects.all(), [ - (u'clearish', Mineral, quartz.pk), - (u'fatty', Animal, platypus.pk), - (u'fatty', Vegetable, bacon.pk), - (u'hairy', Animal, lion.pk), - (u'salty', Vegetable, bacon.pk), - (u'shiny', Animal, platypus.pk), - (u'yellow', Animal, lion.pk) - ], - comp_func - ) - lion.delete() - self.assertQuerysetEqual(TaggedItem.objects.all(), [ - (u'clearish', Mineral, quartz.pk), - (u'fatty', Animal, platypus.pk), - (u'fatty', Vegetable, bacon.pk), - (u'salty', Vegetable, bacon.pk), - (u'shiny', Animal, platypus.pk) - ], - comp_func - ) - - # If Generic Relation is not explicitly defined, any related objects - # remain after deletion of the source object. - quartz_pk = quartz.pk - quartz.delete() - self.assertQuerysetEqual(TaggedItem.objects.all(), [ - (u'clearish', Mineral, quartz_pk), - (u'fatty', Animal, platypus.pk), - (u'fatty', Vegetable, bacon.pk), - (u'salty', Vegetable, bacon.pk), - (u'shiny', Animal, platypus.pk) - ], - comp_func - ) - # If you delete a tag, the objects using the tag are unaffected - # (other than losing a tag) - tag = TaggedItem.objects.order_by("id")[0] - tag.delete() - self.assertQuerysetEqual(bacon.tags.all(), ["<TaggedItem: salty>"]) - self.assertQuerysetEqual(TaggedItem.objects.all(), [ - (u'clearish', Mineral, quartz_pk), - (u'fatty', Animal, platypus.pk), - (u'salty', Vegetable, bacon.pk), - (u'shiny', Animal, platypus.pk) - ], - comp_func - ) - TaggedItem.objects.filter(tag='fatty').delete() - ctype = ContentType.objects.get_for_model(lion) - self.assertQuerysetEqual(Animal.objects.filter(tags__content_type=ctype), [ - "<Animal: Platypus>" - ]) - - - def test_multiple_gfk(self): - # Simple tests for multiple GenericForeignKeys - # only uses one model, since the above tests should be sufficient. - tiger = Animal.objects.create(common_name="tiger") - cheetah = Animal.objects.create(common_name="cheetah") - bear = Animal.objects.create(common_name="bear") - - # Create directly - Comparison.objects.create( - first_obj=cheetah, other_obj=tiger, comparative="faster" - ) - Comparison.objects.create( - first_obj=tiger, other_obj=cheetah, comparative="cooler" - ) - - # Create using GenericRelation - tiger.comparisons.create(other_obj=bear, comparative="cooler") - tiger.comparisons.create(other_obj=cheetah, comparative="stronger") - self.assertQuerysetEqual(cheetah.comparisons.all(), [ - "<Comparison: cheetah is faster than tiger>" - ]) - - # Filtering works - self.assertQuerysetEqual(tiger.comparisons.filter(comparative="cooler"), [ - "<Comparison: tiger is cooler than cheetah>", - "<Comparison: tiger is cooler than bear>" - ]) - - # Filtering and deleting works - subjective = ["cooler"] - tiger.comparisons.filter(comparative__in=subjective).delete() - self.assertQuerysetEqual(Comparison.objects.all(), [ - "<Comparison: cheetah is faster than tiger>", - "<Comparison: tiger is stronger than cheetah>" - ]) - - # If we delete cheetah, Comparisons with cheetah as 'first_obj' will be - # deleted since Animal has an explicit GenericRelation to Comparison - # through first_obj. Comparisons with cheetah as 'other_obj' will not - # be deleted. - cheetah.delete() - self.assertQuerysetEqual(Comparison.objects.all(), [ - "<Comparison: tiger is stronger than None>" - ]) - - def test_gfk_subclasses(self): - # GenericForeignKey should work with subclasses (see #8309) - quartz = Mineral.objects.create(name="Quartz", hardness=7) - valuedtag = ValuableTaggedItem.objects.create( - content_object=quartz, tag="shiny", value=10 - ) - self.assertEqual(valuedtag.content_object, quartz) - - def test_generic_inline_formsets(self): - GenericFormSet = generic_inlineformset_factory(TaggedItem, extra=1) - formset = GenericFormSet() - self.assertEqual(u''.join(form.as_p() for form in formset.forms), u"""<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-tag">Tag:</label> <input id="id_generic_relations-taggeditem-content_type-object_id-0-tag" type="text" name="generic_relations-taggeditem-content_type-object_id-0-tag" maxlength="50" /></p> -<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-DELETE">Delete:</label> <input type="checkbox" name="generic_relations-taggeditem-content_type-object_id-0-DELETE" id="id_generic_relations-taggeditem-content_type-object_id-0-DELETE" /><input type="hidden" name="generic_relations-taggeditem-content_type-object_id-0-id" id="id_generic_relations-taggeditem-content_type-object_id-0-id" /></p>""") - - formset = GenericFormSet(instance=Animal()) - self.assertEqual(u''.join(form.as_p() for form in formset.forms), u"""<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-tag">Tag:</label> <input id="id_generic_relations-taggeditem-content_type-object_id-0-tag" type="text" name="generic_relations-taggeditem-content_type-object_id-0-tag" maxlength="50" /></p> -<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-DELETE">Delete:</label> <input type="checkbox" name="generic_relations-taggeditem-content_type-object_id-0-DELETE" id="id_generic_relations-taggeditem-content_type-object_id-0-DELETE" /><input type="hidden" name="generic_relations-taggeditem-content_type-object_id-0-id" id="id_generic_relations-taggeditem-content_type-object_id-0-id" /></p>""") - - platypus = Animal.objects.create( - common_name="Platypus", latin_name="Ornithorhynchus anatinus" - ) - platypus.tags.create(tag="shiny") - GenericFormSet = generic_inlineformset_factory(TaggedItem, extra=1) - formset = GenericFormSet(instance=platypus) - tagged_item_id = TaggedItem.objects.get( - tag='shiny', object_id=platypus.id - ).id - self.assertEqual(u''.join(form.as_p() for form in formset.forms), u"""<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-tag">Tag:</label> <input id="id_generic_relations-taggeditem-content_type-object_id-0-tag" type="text" name="generic_relations-taggeditem-content_type-object_id-0-tag" value="shiny" maxlength="50" /></p> -<p><label for="id_generic_relations-taggeditem-content_type-object_id-0-DELETE">Delete:</label> <input type="checkbox" name="generic_relations-taggeditem-content_type-object_id-0-DELETE" id="id_generic_relations-taggeditem-content_type-object_id-0-DELETE" /><input type="hidden" name="generic_relations-taggeditem-content_type-object_id-0-id" value="%s" id="id_generic_relations-taggeditem-content_type-object_id-0-id" /></p><p><label for="id_generic_relations-taggeditem-content_type-object_id-1-tag">Tag:</label> <input id="id_generic_relations-taggeditem-content_type-object_id-1-tag" type="text" name="generic_relations-taggeditem-content_type-object_id-1-tag" maxlength="50" /></p> -<p><label for="id_generic_relations-taggeditem-content_type-object_id-1-DELETE">Delete:</label> <input type="checkbox" name="generic_relations-taggeditem-content_type-object_id-1-DELETE" id="id_generic_relations-taggeditem-content_type-object_id-1-DELETE" /><input type="hidden" name="generic_relations-taggeditem-content_type-object_id-1-id" id="id_generic_relations-taggeditem-content_type-object_id-1-id" /></p>""" % tagged_item_id) - - lion = Animal.objects.create(common_name="Lion", latin_name="Panthera leo") - formset = GenericFormSet(instance=lion, prefix='x') - self.assertEqual(u''.join(form.as_p() for form in formset.forms), u"""<p><label for="id_x-0-tag">Tag:</label> <input id="id_x-0-tag" type="text" name="x-0-tag" maxlength="50" /></p> -<p><label for="id_x-0-DELETE">Delete:</label> <input type="checkbox" name="x-0-DELETE" id="id_x-0-DELETE" /><input type="hidden" name="x-0-id" id="id_x-0-id" /></p>""") diff --git a/parts/django/tests/modeltests/get_latest/__init__.py b/parts/django/tests/modeltests/get_latest/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/get_latest/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/get_latest/models.py b/parts/django/tests/modeltests/get_latest/models.py deleted file mode 100644 index 1eeb299..0000000 --- a/parts/django/tests/modeltests/get_latest/models.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -8. get_latest_by - -Models can have a ``get_latest_by`` attribute, which should be set to the name -of a ``DateField`` or ``DateTimeField``. If ``get_latest_by`` exists, the -model's manager will get a ``latest()`` method, which will return the latest -object in the database according to that field. "Latest" means "having the date -farthest into the future." -""" - -from django.db import models - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateField() - expire_date = models.DateField() - class Meta: - get_latest_by = 'pub_date' - - def __unicode__(self): - return self.headline - -class Person(models.Model): - name = models.CharField(max_length=30) - birthday = models.DateField() - - # Note that this model doesn't have "get_latest_by" set. - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/get_latest/tests.py b/parts/django/tests/modeltests/get_latest/tests.py deleted file mode 100644 index 3c3588b..0000000 --- a/parts/django/tests/modeltests/get_latest/tests.py +++ /dev/null @@ -1,53 +0,0 @@ -from datetime import datetime - -from django.test import TestCase - -from models import Article, Person - - -class LatestTests(TestCase): - def test_latest(self): - # Because no Articles exist yet, latest() raises ArticleDoesNotExist. - self.assertRaises(Article.DoesNotExist, Article.objects.latest) - - a1 = Article.objects.create( - headline="Article 1", pub_date=datetime(2005, 7, 26), - expire_date=datetime(2005, 9, 1) - ) - a2 = Article.objects.create( - headline="Article 2", pub_date=datetime(2005, 7, 27), - expire_date=datetime(2005, 7, 28) - ) - a3 = Article.objects.create( - headline="Article 3", pub_date=datetime(2005, 7, 27), - expire_date=datetime(2005, 8, 27) - ) - a4 = Article.objects.create( - headline="Article 4", pub_date=datetime(2005, 7, 28), - expire_date=datetime(2005, 7, 30) - ) - - # Get the latest Article. - self.assertEqual(Article.objects.latest(), a4) - # Get the latest Article that matches certain filters. - self.assertEqual( - Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest(), - a1 - ) - - # Pass a custom field name to latest() to change the field that's used - # to determine the latest object. - self.assertEqual(Article.objects.latest('expire_date'), a1) - self.assertEqual( - Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date'), - a3, - ) - - def test_latest_manual(self): - # You can still use latest() with a model that doesn't have - # "get_latest_by" set -- just pass in the field name manually. - p1 = Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1)) - p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3)) - self.assertRaises(AssertionError, Person.objects.latest) - - self.assertEqual(Person.objects.latest("birthday"), p2) diff --git a/parts/django/tests/modeltests/get_object_or_404/__init__.py b/parts/django/tests/modeltests/get_object_or_404/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/get_object_or_404/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/get_object_or_404/models.py b/parts/django/tests/modeltests/get_object_or_404/models.py deleted file mode 100644 index eb3cd82..0000000 --- a/parts/django/tests/modeltests/get_object_or_404/models.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -35. DB-API Shortcuts - -``get_object_or_404()`` is a shortcut function to be used in view functions for -performing a ``get()`` lookup and raising a ``Http404`` exception if a -``DoesNotExist`` exception was raised during the ``get()`` call. - -``get_list_or_404()`` is a shortcut function to be used in view functions for -performing a ``filter()`` lookup and raising a ``Http404`` exception if a -``DoesNotExist`` exception was raised during the ``filter()`` call. -""" - -from django.db import models -from django.http import Http404 -from django.shortcuts import get_object_or_404, get_list_or_404 - -class Author(models.Model): - name = models.CharField(max_length=50) - - def __unicode__(self): - return self.name - -class ArticleManager(models.Manager): - def get_query_set(self): - return super(ArticleManager, self).get_query_set().filter(authors__name__icontains='sir') - -class Article(models.Model): - authors = models.ManyToManyField(Author) - title = models.CharField(max_length=50) - objects = models.Manager() - by_a_sir = ArticleManager() - - def __unicode__(self): - return self.title diff --git a/parts/django/tests/modeltests/get_object_or_404/tests.py b/parts/django/tests/modeltests/get_object_or_404/tests.py deleted file mode 100644 index b8c4f75..0000000 --- a/parts/django/tests/modeltests/get_object_or_404/tests.py +++ /dev/null @@ -1,80 +0,0 @@ -from django.http import Http404 -from django.shortcuts import get_object_or_404, get_list_or_404 -from django.test import TestCase - -from models import Author, Article - - -class GetObjectOr404Tests(TestCase): - def test_get_object_or_404(self): - a1 = Author.objects.create(name="Brave Sir Robin") - a2 = Author.objects.create(name="Patsy") - - # No Articles yet, so we should get a Http404 error. - self.assertRaises(Http404, get_object_or_404, Article, title="Foo") - - article = Article.objects.create(title="Run away!") - article.authors = [a1, a2] - # get_object_or_404 can be passed a Model to query. - self.assertEqual( - get_object_or_404(Article, title__contains="Run"), - article - ) - - # We can also use the Article manager through an Author object. - self.assertEqual( - get_object_or_404(a1.article_set, title__contains="Run"), - article - ) - - # No articles containing "Camelot". This should raise a Http404 error. - self.assertRaises(Http404, - get_object_or_404, a1.article_set, title__contains="Camelot" - ) - - # Custom managers can be used too. - self.assertEqual( - get_object_or_404(Article.by_a_sir, title="Run away!"), - article - ) - - # QuerySets can be used too. - self.assertEqual( - get_object_or_404(Article.objects.all(), title__contains="Run"), - article - ) - - # Just as when using a get() lookup, you will get an error if more than - # one object is returned. - - self.assertRaises(Author.MultipleObjectsReturned, - get_object_or_404, Author.objects.all() - ) - - # Using an EmptyQuerySet raises a Http404 error. - self.assertRaises(Http404, - get_object_or_404, Article.objects.none(), title__contains="Run" - ) - - # get_list_or_404 can be used to get lists of objects - self.assertEqual( - get_list_or_404(a1.article_set, title__icontains="Run"), - [article] - ) - - # Http404 is returned if the list is empty. - self.assertRaises(Http404, - get_list_or_404, a1.article_set, title__icontains="Shrubbery" - ) - - # Custom managers can be used too. - self.assertEqual( - get_list_or_404(Article.by_a_sir, title__icontains="Run"), - [article] - ) - - # QuerySets can be used too. - self.assertEqual( - get_list_or_404(Article.objects.all(), title__icontains="Run"), - [article] - ) diff --git a/parts/django/tests/modeltests/get_or_create/__init__.py b/parts/django/tests/modeltests/get_or_create/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/get_or_create/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/get_or_create/models.py b/parts/django/tests/modeltests/get_or_create/models.py deleted file mode 100644 index db5719b..0000000 --- a/parts/django/tests/modeltests/get_or_create/models.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -33. get_or_create() - -``get_or_create()`` does what it says: it tries to look up an object with the -given parameters. If an object isn't found, it creates one with the given -parameters. -""" - -from django.db import models, IntegrityError - -class Person(models.Model): - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - birthday = models.DateField() - - def __unicode__(self): - return u'%s %s' % (self.first_name, self.last_name) - -class ManualPrimaryKeyTest(models.Model): - id = models.IntegerField(primary_key=True) - data = models.CharField(max_length=100) diff --git a/parts/django/tests/modeltests/get_or_create/tests.py b/parts/django/tests/modeltests/get_or_create/tests.py deleted file mode 100644 index 1999b20..0000000 --- a/parts/django/tests/modeltests/get_or_create/tests.py +++ /dev/null @@ -1,52 +0,0 @@ -from datetime import date - -from django.db import IntegrityError -from django.test import TransactionTestCase - -from models import Person, ManualPrimaryKeyTest - - -class GetOrCreateTests(TransactionTestCase): - def test_get_or_create(self): - p = Person.objects.create( - first_name='John', last_name='Lennon', birthday=date(1940, 10, 9) - ) - - p, created = Person.objects.get_or_create( - first_name="John", last_name="Lennon", defaults={ - "birthday": date(1940, 10, 9) - } - ) - self.assertFalse(created) - self.assertEqual(Person.objects.count(), 1) - - p, created = Person.objects.get_or_create( - first_name='George', last_name='Harrison', defaults={ - 'birthday': date(1943, 2, 25) - } - ) - self.assertTrue(created) - self.assertEqual(Person.objects.count(), 2) - - # If we execute the exact same statement, it won't create a Person. - p, created = Person.objects.get_or_create( - first_name='George', last_name='Harrison', defaults={ - 'birthday': date(1943, 2, 25) - } - ) - self.assertFalse(created) - self.assertEqual(Person.objects.count(), 2) - - # If you don't specify a value or default value for all required - # fields, you will get an error. - self.assertRaises(IntegrityError, - Person.objects.get_or_create, first_name="Tom", last_name="Smith" - ) - - # If you specify an existing primary key, but different other fields, - # then you will get an error and data will not be updated. - m = ManualPrimaryKeyTest.objects.create(id=1, data="Original") - self.assertRaises(IntegrityError, - ManualPrimaryKeyTest.objects.get_or_create, id=1, data="Different" - ) - self.assertEqual(ManualPrimaryKeyTest.objects.get(id=1).data, "Original") diff --git a/parts/django/tests/modeltests/invalid_models/__init__.py b/parts/django/tests/modeltests/invalid_models/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/parts/django/tests/modeltests/invalid_models/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/parts/django/tests/modeltests/invalid_models/models.py b/parts/django/tests/modeltests/invalid_models/models.py deleted file mode 100644 index 09301ed..0000000 --- a/parts/django/tests/modeltests/invalid_models/models.py +++ /dev/null @@ -1,335 +0,0 @@ -""" -26. Invalid models - -This example exists purely to point out errors in models. -""" - -from django.contrib.contenttypes import generic -from django.db import models - -class FieldErrors(models.Model): - charfield = models.CharField() - charfield2 = models.CharField(max_length=-1) - charfield3 = models.CharField(max_length="bad") - decimalfield = models.DecimalField() - decimalfield2 = models.DecimalField(max_digits=-1, decimal_places=-1) - decimalfield3 = models.DecimalField(max_digits="bad", decimal_places="bad") - filefield = models.FileField() - choices = models.CharField(max_length=10, choices='bad') - choices2 = models.CharField(max_length=10, choices=[(1,2,3),(1,2,3)]) - index = models.CharField(max_length=10, db_index='bad') - field_ = models.CharField(max_length=10) - nullbool = models.BooleanField(null=True) - -class Target(models.Model): - tgt_safe = models.CharField(max_length=10) - clash1 = models.CharField(max_length=10) - clash2 = models.CharField(max_length=10) - - clash1_set = models.CharField(max_length=10) - -class Clash1(models.Model): - src_safe = models.CharField(max_length=10) - - foreign = models.ForeignKey(Target) - m2m = models.ManyToManyField(Target) - -class Clash2(models.Model): - src_safe = models.CharField(max_length=10) - - foreign_1 = models.ForeignKey(Target, related_name='id') - foreign_2 = models.ForeignKey(Target, related_name='src_safe') - - m2m_1 = models.ManyToManyField(Target, related_name='id') - m2m_2 = models.ManyToManyField(Target, related_name='src_safe') - -class Target2(models.Model): - clash3 = models.CharField(max_length=10) - foreign_tgt = models.ForeignKey(Target) - clashforeign_set = models.ForeignKey(Target) - - m2m_tgt = models.ManyToManyField(Target) - clashm2m_set = models.ManyToManyField(Target) - -class Clash3(models.Model): - src_safe = models.CharField(max_length=10) - - foreign_1 = models.ForeignKey(Target2, related_name='foreign_tgt') - foreign_2 = models.ForeignKey(Target2, related_name='m2m_tgt') - - m2m_1 = models.ManyToManyField(Target2, related_name='foreign_tgt') - m2m_2 = models.ManyToManyField(Target2, related_name='m2m_tgt') - -class ClashForeign(models.Model): - foreign = models.ForeignKey(Target2) - -class ClashM2M(models.Model): - m2m = models.ManyToManyField(Target2) - -class SelfClashForeign(models.Model): - src_safe = models.CharField(max_length=10) - selfclashforeign = models.CharField(max_length=10) - - selfclashforeign_set = models.ForeignKey("SelfClashForeign") - foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id') - foreign_2 = models.ForeignKey("SelfClashForeign", related_name='src_safe') - -class ValidM2M(models.Model): - src_safe = models.CharField(max_length=10) - validm2m = models.CharField(max_length=10) - - # M2M fields are symmetrical by default. Symmetrical M2M fields - # on self don't require a related accessor, so many potential - # clashes are avoided. - validm2m_set = models.ManyToManyField("self") - - m2m_1 = models.ManyToManyField("self", related_name='id') - m2m_2 = models.ManyToManyField("self", related_name='src_safe') - - m2m_3 = models.ManyToManyField('self') - m2m_4 = models.ManyToManyField('self') - -class SelfClashM2M(models.Model): - src_safe = models.CharField(max_length=10) - selfclashm2m = models.CharField(max_length=10) - - # Non-symmetrical M2M fields _do_ have related accessors, so - # there is potential for clashes. - selfclashm2m_set = models.ManyToManyField("self", symmetrical=False) - - m2m_1 = models.ManyToManyField("self", related_name='id', symmetrical=False) - m2m_2 = models.ManyToManyField("self", related_name='src_safe', symmetrical=False) - - m2m_3 = models.ManyToManyField('self', symmetrical=False) - m2m_4 = models.ManyToManyField('self', symmetrical=False) - -class Model(models.Model): - "But it's valid to call a model Model." - year = models.PositiveIntegerField() #1960 - make = models.CharField(max_length=10) #Aston Martin - name = models.CharField(max_length=10) #DB 4 GT - -class Car(models.Model): - colour = models.CharField(max_length=5) - model = models.ForeignKey(Model) - -class MissingRelations(models.Model): - rel1 = models.ForeignKey("Rel1") - rel2 = models.ManyToManyField("Rel2") - -class MissingManualM2MModel(models.Model): - name = models.CharField(max_length=5) - missing_m2m = models.ManyToManyField(Model, through="MissingM2MModel") - -class Person(models.Model): - name = models.CharField(max_length=5) - -class Group(models.Model): - name = models.CharField(max_length=5) - primary = models.ManyToManyField(Person, through="Membership", related_name="primary") - secondary = models.ManyToManyField(Person, through="Membership", related_name="secondary") - tertiary = models.ManyToManyField(Person, through="RelationshipDoubleFK", related_name="tertiary") - -class GroupTwo(models.Model): - name = models.CharField(max_length=5) - primary = models.ManyToManyField(Person, through="Membership") - secondary = models.ManyToManyField(Group, through="MembershipMissingFK") - -class Membership(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - not_default_or_null = models.CharField(max_length=5) - -class MembershipMissingFK(models.Model): - person = models.ForeignKey(Person) - -class PersonSelfRefM2M(models.Model): - name = models.CharField(max_length=5) - friends = models.ManyToManyField('self', through="Relationship") - too_many_friends = models.ManyToManyField('self', through="RelationshipTripleFK") - -class PersonSelfRefM2MExplicit(models.Model): - name = models.CharField(max_length=5) - friends = models.ManyToManyField('self', through="ExplicitRelationship", symmetrical=True) - -class Relationship(models.Model): - first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set") - second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set") - date_added = models.DateTimeField() - -class ExplicitRelationship(models.Model): - first = models.ForeignKey(PersonSelfRefM2MExplicit, related_name="rel_from_set") - second = models.ForeignKey(PersonSelfRefM2MExplicit, related_name="rel_to_set") - date_added = models.DateTimeField() - -class RelationshipTripleFK(models.Model): - first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set_2") - second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set_2") - third = models.ForeignKey(PersonSelfRefM2M, related_name="too_many_by_far") - date_added = models.DateTimeField() - -class RelationshipDoubleFK(models.Model): - first = models.ForeignKey(Person, related_name="first_related_name") - second = models.ForeignKey(Person, related_name="second_related_name") - third = models.ForeignKey(Group, related_name="rel_to_set") - date_added = models.DateTimeField() - -class AbstractModel(models.Model): - name = models.CharField(max_length=10) - class Meta: - abstract = True - -class AbstractRelationModel(models.Model): - fk1 = models.ForeignKey('AbstractModel') - fk2 = models.ManyToManyField('AbstractModel') - -class UniqueM2M(models.Model): - """ Model to test for unique ManyToManyFields, which are invalid. """ - unique_people = models.ManyToManyField(Person, unique=True) - -class NonUniqueFKTarget1(models.Model): - """ Model to test for non-unique FK target in yet-to-be-defined model: expect an error """ - tgt = models.ForeignKey('FKTarget', to_field='bad') - -class UniqueFKTarget1(models.Model): - """ Model to test for unique FK target in yet-to-be-defined model: expect no error """ - tgt = models.ForeignKey('FKTarget', to_field='good') - -class FKTarget(models.Model): - bad = models.IntegerField() - good = models.IntegerField(unique=True) - -class NonUniqueFKTarget2(models.Model): - """ Model to test for non-unique FK target in previously seen model: expect an error """ - tgt = models.ForeignKey(FKTarget, to_field='bad') - -class UniqueFKTarget2(models.Model): - """ Model to test for unique FK target in previously seen model: expect no error """ - tgt = models.ForeignKey(FKTarget, to_field='good') - -class NonExistingOrderingWithSingleUnderscore(models.Model): - class Meta: - ordering = ("does_not_exist",) - -class Tag(models.Model): - name = models.CharField("name", max_length=20) - -class TaggedObject(models.Model): - object_id = models.PositiveIntegerField("Object ID") - tag = models.ForeignKey(Tag) - content_object = generic.GenericForeignKey() - -class UserTaggedObject(models.Model): - object_tag = models.ForeignKey(TaggedObject) - -class ArticleAttachment(models.Model): - tags = generic.GenericRelation(TaggedObject) - user_tags = generic.GenericRelation(UserTaggedObject) - -model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute that is a positive integer. -invalid_models.fielderrors: "charfield2": CharFields require a "max_length" attribute that is a positive integer. -invalid_models.fielderrors: "charfield3": CharFields require a "max_length" attribute that is a positive integer. -invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute that is a non-negative integer. -invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute that is a positive integer. -invalid_models.fielderrors: "decimalfield2": DecimalFields require a "decimal_places" attribute that is a non-negative integer. -invalid_models.fielderrors: "decimalfield2": DecimalFields require a "max_digits" attribute that is a positive integer. -invalid_models.fielderrors: "decimalfield3": DecimalFields require a "decimal_places" attribute that is a non-negative integer. -invalid_models.fielderrors: "decimalfield3": DecimalFields require a "max_digits" attribute that is a positive integer. -invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute. -invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list). -invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. -invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. -invalid_models.fielderrors: "index": "db_index" should be either None, True or False. -invalid_models.fielderrors: "field_": Field names cannot end with underscores, because this would lead to ambiguous queryset filters. -invalid_models.fielderrors: "nullbool": BooleanFields do not accept null values. Use a NullBooleanField instead. -invalid_models.clash1: Accessor for field 'foreign' clashes with field 'Target.clash1_set'. Add a related_name argument to the definition for 'foreign'. -invalid_models.clash1: Accessor for field 'foreign' clashes with related m2m field 'Target.clash1_set'. Add a related_name argument to the definition for 'foreign'. -invalid_models.clash1: Reverse query name for field 'foreign' clashes with field 'Target.clash1'. Add a related_name argument to the definition for 'foreign'. -invalid_models.clash1: Accessor for m2m field 'm2m' clashes with field 'Target.clash1_set'. Add a related_name argument to the definition for 'm2m'. -invalid_models.clash1: Accessor for m2m field 'm2m' clashes with related field 'Target.clash1_set'. Add a related_name argument to the definition for 'm2m'. -invalid_models.clash1: Reverse query name for m2m field 'm2m' clashes with field 'Target.clash1'. Add a related_name argument to the definition for 'm2m'. -invalid_models.clash2: Accessor for field 'foreign_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash2: Accessor for field 'foreign_1' clashes with related m2m field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash2: Reverse query name for field 'foreign_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash2: Reverse query name for field 'foreign_1' clashes with related m2m field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash2: Accessor for field 'foreign_2' clashes with related m2m field 'Target.src_safe'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash2: Reverse query name for field 'foreign_2' clashes with related m2m field 'Target.src_safe'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash2: Accessor for m2m field 'm2m_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash2: Accessor for m2m field 'm2m_1' clashes with related field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash2: Reverse query name for m2m field 'm2m_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash2: Reverse query name for m2m field 'm2m_1' clashes with related field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash2: Accessor for m2m field 'm2m_2' clashes with related field 'Target.src_safe'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clash2: Reverse query name for m2m field 'm2m_2' clashes with related field 'Target.src_safe'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clash3: Accessor for field 'foreign_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash3: Accessor for field 'foreign_1' clashes with related m2m field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash3: Reverse query name for field 'foreign_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash3: Reverse query name for field 'foreign_1' clashes with related m2m field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.clash3: Accessor for field 'foreign_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash3: Accessor for field 'foreign_2' clashes with related m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash3: Reverse query name for field 'foreign_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash3: Reverse query name for field 'foreign_2' clashes with related m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.clash3: Accessor for m2m field 'm2m_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash3: Accessor for m2m field 'm2m_1' clashes with related field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash3: Reverse query name for m2m field 'm2m_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash3: Reverse query name for m2m field 'm2m_1' clashes with related field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.clash3: Accessor for m2m field 'm2m_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clash3: Accessor for m2m field 'm2m_2' clashes with related field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clash3: Reverse query name for m2m field 'm2m_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clash3: Reverse query name for m2m field 'm2m_2' clashes with related field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.clashforeign: Accessor for field 'foreign' clashes with field 'Target2.clashforeign_set'. Add a related_name argument to the definition for 'foreign'. -invalid_models.clashm2m: Accessor for m2m field 'm2m' clashes with m2m field 'Target2.clashm2m_set'. Add a related_name argument to the definition for 'm2m'. -invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. -invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. -invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. -invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. -invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. -invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. -invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. -invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. -invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. -invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. -invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. -invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. -invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. -invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. -invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. -invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. -invalid_models.selfclashforeign: Accessor for field 'selfclashforeign_set' clashes with field 'SelfClashForeign.selfclashforeign_set'. Add a related_name argument to the definition for 'selfclashforeign_set'. -invalid_models.selfclashforeign: Reverse query name for field 'selfclashforeign_set' clashes with field 'SelfClashForeign.selfclashforeign'. Add a related_name argument to the definition for 'selfclashforeign_set'. -invalid_models.selfclashforeign: Accessor for field 'foreign_1' clashes with field 'SelfClashForeign.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.selfclashforeign: Reverse query name for field 'foreign_1' clashes with field 'SelfClashForeign.id'. Add a related_name argument to the definition for 'foreign_1'. -invalid_models.selfclashforeign: Accessor for field 'foreign_2' clashes with field 'SelfClashForeign.src_safe'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.selfclashforeign: Reverse query name for field 'foreign_2' clashes with field 'SelfClashForeign.src_safe'. Add a related_name argument to the definition for 'foreign_2'. -invalid_models.selfclashm2m: Accessor for m2m field 'selfclashm2m_set' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'selfclashm2m_set'. -invalid_models.selfclashm2m: Reverse query name for m2m field 'selfclashm2m_set' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'selfclashm2m_set'. -invalid_models.selfclashm2m: Accessor for m2m field 'selfclashm2m_set' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'selfclashm2m_set'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'. -invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_3' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_3'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'. -invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'. -invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_3' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_3'. -invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_4' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_4'. -invalid_models.missingrelations: 'rel1' has a relation with model Rel1, which has either not been installed or is abstract. -invalid_models.missingrelations: 'rel2' has an m2m relation with model Rel2, which has either not been installed or is abstract. -invalid_models.grouptwo: 'primary' is a manually-defined m2m relation through model Membership, which does not have foreign keys to Person and GroupTwo -invalid_models.grouptwo: 'secondary' is a manually-defined m2m relation through model MembershipMissingFK, which does not have foreign keys to Group and GroupTwo -invalid_models.missingmanualm2mmodel: 'missing_m2m' specifies an m2m relation through model MissingM2MModel, which has not been installed -invalid_models.group: The model Group has two manually-defined m2m relations through the model Membership, which is not permitted. Please consider using an extra field on your intermediary model instead. -invalid_models.group: Intermediary model RelationshipDoubleFK has more than one foreign key to Person, which is ambiguous and is not permitted. -invalid_models.personselfrefm2m: Many-to-many fields with intermediate tables cannot be symmetrical. -invalid_models.personselfrefm2m: Intermediary model RelationshipTripleFK has more than two foreign keys to PersonSelfRefM2M, which is ambiguous and is not permitted. -invalid_models.personselfrefm2mexplicit: Many-to-many fields with intermediate tables cannot be symmetrical. -invalid_models.abstractrelationmodel: 'fk1' has a relation with model AbstractModel, which has either not been installed or is abstract. -invalid_models.abstractrelationmodel: 'fk2' has an m2m relation with model AbstractModel, which has either not been installed or is abstract. -invalid_models.uniquem2m: ManyToManyFields cannot be unique. Remove the unique argument on 'unique_people'. -invalid_models.nonuniquefktarget1: Field 'bad' under model 'FKTarget' must have a unique=True constraint. -invalid_models.nonuniquefktarget2: Field 'bad' under model 'FKTarget' must have a unique=True constraint. -invalid_models.nonexistingorderingwithsingleunderscore: "ordering" refers to "does_not_exist", a field that doesn't exist. -invalid_models.articleattachment: Model 'UserTaggedObject' must have a GenericForeignKey in order to create a GenericRelation that points to it. -""" diff --git a/parts/django/tests/modeltests/lookup/__init__.py b/parts/django/tests/modeltests/lookup/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/lookup/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/lookup/models.py b/parts/django/tests/modeltests/lookup/models.py deleted file mode 100644 index 99eec51..0000000 --- a/parts/django/tests/modeltests/lookup/models.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -7. The lookup API - -This demonstrates features of the database API. -""" - -from django.db import models - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateTimeField() - class Meta: - ordering = ('-pub_date', 'headline') - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/lookup/tests.py b/parts/django/tests/modeltests/lookup/tests.py deleted file mode 100644 index 9e0b68e..0000000 --- a/parts/django/tests/modeltests/lookup/tests.py +++ /dev/null @@ -1,547 +0,0 @@ -from datetime import datetime -from operator import attrgetter - -from django.conf import settings -from django.core.exceptions import FieldError -from django.db import connection, DEFAULT_DB_ALIAS -from django.test import TestCase - -from models import Article - -class LookupTests(TestCase): - - #def setUp(self): - def setUp(self): - # Create a couple of Articles. - self.a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26)) - self.a1.save() - self.a2 = Article(headline='Article 2', pub_date=datetime(2005, 7, 27)) - self.a2.save() - self.a3 = Article(headline='Article 3', pub_date=datetime(2005, 7, 27)) - self.a3.save() - self.a4 = Article(headline='Article 4', pub_date=datetime(2005, 7, 28)) - self.a4.save() - self.a5 = Article(headline='Article 5', pub_date=datetime(2005, 8, 1, 9, 0)) - self.a5.save() - self.a6 = Article(headline='Article 6', pub_date=datetime(2005, 8, 1, 8, 0)) - self.a6.save() - self.a7 = Article(headline='Article 7', pub_date=datetime(2005, 7, 27)) - self.a7.save() - - def test_exists(self): - # We can use .exists() to check that there are some - self.assertTrue(Article.objects.exists()) - for a in Article.objects.all(): - a.delete() - # There should be none now! - self.assertFalse(Article.objects.exists()) - - def test_lookup_int_as_str(self): - # Integer value can be queried using string - self.assertQuerysetEqual(Article.objects.filter(id__iexact=str(self.a1.id)), - ['<Article: Article 1>']) - - if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] in ( - 'django.db.backends.postgresql', - 'django.db.backends.postgresql_psycopg2'): - def test_lookup_date_as_str(self): - # A date lookup can be performed using a string search - self.assertQuerysetEqual(Article.objects.filter(pub_date__startswith='2005'), - [ - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - - def test_iterator(self): - # Each QuerySet gets iterator(), which is a generator that "lazily" - # returns results using database-level iteration. - self.assertQuerysetEqual(Article.objects.iterator(), - [ - 'Article 5', - 'Article 6', - 'Article 4', - 'Article 2', - 'Article 3', - 'Article 7', - 'Article 1', - ], - transform=attrgetter('headline')) - # iterator() can be used on any QuerySet. - self.assertQuerysetEqual( - Article.objects.filter(headline__endswith='4').iterator(), - ['Article 4'], - transform=attrgetter('headline')) - - def test_count(self): - # count() returns the number of objects matching search criteria. - self.assertEqual(Article.objects.count(), 7) - self.assertEqual(Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).count(), 3) - self.assertEqual(Article.objects.filter(headline__startswith='Blah blah').count(), 0) - - # count() should respect sliced query sets. - articles = Article.objects.all() - self.assertEqual(articles.count(), 7) - self.assertEqual(articles[:4].count(), 4) - self.assertEqual(articles[1:100].count(), 6) - self.assertEqual(articles[10:100].count(), 0) - - # Date and date/time lookups can also be done with strings. - self.assertEqual(Article.objects.filter(pub_date__exact='2005-07-27 00:00:00').count(), 3) - - def test_in_bulk(self): - # in_bulk() takes a list of IDs and returns a dictionary mapping IDs to objects. - arts = Article.objects.in_bulk([self.a1.id, self.a2.id]) - self.assertEqual(arts[self.a1.id], self.a1) - self.assertEqual(arts[self.a2.id], self.a2) - self.assertEqual(Article.objects.in_bulk([self.a3.id]), {self.a3.id: self.a3}) - self.assertEqual(Article.objects.in_bulk(set([self.a3.id])), {self.a3.id: self.a3}) - self.assertEqual(Article.objects.in_bulk(frozenset([self.a3.id])), {self.a3.id: self.a3}) - self.assertEqual(Article.objects.in_bulk((self.a3.id,)), {self.a3.id: self.a3}) - self.assertEqual(Article.objects.in_bulk([1000]), {}) - self.assertEqual(Article.objects.in_bulk([]), {}) - self.assertRaises(AssertionError, Article.objects.in_bulk, 'foo') - self.assertRaises(TypeError, Article.objects.in_bulk) - self.assertRaises(TypeError, Article.objects.in_bulk, headline__startswith='Blah') - - def test_values(self): - # values() returns a list of dictionaries instead of object instances -- - # and you can specify which fields you want to retrieve. - identity = lambda x:x - self.assertQuerysetEqual(Article.objects.values('headline'), - [ - {'headline': u'Article 5'}, - {'headline': u'Article 6'}, - {'headline': u'Article 4'}, - {'headline': u'Article 2'}, - {'headline': u'Article 3'}, - {'headline': u'Article 7'}, - {'headline': u'Article 1'}, - ], - transform=identity) - self.assertQuerysetEqual( - Article.objects.filter(pub_date__exact=datetime(2005, 7, 27)).values('id'), - [{'id': self.a2.id}, {'id': self.a3.id}, {'id': self.a7.id}], - transform=identity) - self.assertQuerysetEqual(Article.objects.values('id', 'headline'), - [ - {'id': self.a5.id, 'headline': 'Article 5'}, - {'id': self.a6.id, 'headline': 'Article 6'}, - {'id': self.a4.id, 'headline': 'Article 4'}, - {'id': self.a2.id, 'headline': 'Article 2'}, - {'id': self.a3.id, 'headline': 'Article 3'}, - {'id': self.a7.id, 'headline': 'Article 7'}, - {'id': self.a1.id, 'headline': 'Article 1'}, - ], - transform=identity) - # You can use values() with iterator() for memory savings, - # because iterator() uses database-level iteration. - self.assertQuerysetEqual(Article.objects.values('id', 'headline').iterator(), - [ - {'headline': u'Article 5', 'id': self.a5.id}, - {'headline': u'Article 6', 'id': self.a6.id}, - {'headline': u'Article 4', 'id': self.a4.id}, - {'headline': u'Article 2', 'id': self.a2.id}, - {'headline': u'Article 3', 'id': self.a3.id}, - {'headline': u'Article 7', 'id': self.a7.id}, - {'headline': u'Article 1', 'id': self.a1.id}, - ], - transform=identity) - # The values() method works with "extra" fields specified in extra(select). - self.assertQuerysetEqual( - Article.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_one'), - [ - {'id': self.a5.id, 'id_plus_one': self.a5.id + 1}, - {'id': self.a6.id, 'id_plus_one': self.a6.id + 1}, - {'id': self.a4.id, 'id_plus_one': self.a4.id + 1}, - {'id': self.a2.id, 'id_plus_one': self.a2.id + 1}, - {'id': self.a3.id, 'id_plus_one': self.a3.id + 1}, - {'id': self.a7.id, 'id_plus_one': self.a7.id + 1}, - {'id': self.a1.id, 'id_plus_one': self.a1.id + 1}, - ], - transform=identity) - data = { - 'id_plus_one': 'id+1', - 'id_plus_two': 'id+2', - 'id_plus_three': 'id+3', - 'id_plus_four': 'id+4', - 'id_plus_five': 'id+5', - 'id_plus_six': 'id+6', - 'id_plus_seven': 'id+7', - 'id_plus_eight': 'id+8', - } - self.assertQuerysetEqual( - Article.objects.filter(id=self.a1.id).extra(select=data).values(*data.keys()), - [{ - 'id_plus_one': self.a1.id + 1, - 'id_plus_two': self.a1.id + 2, - 'id_plus_three': self.a1.id + 3, - 'id_plus_four': self.a1.id + 4, - 'id_plus_five': self.a1.id + 5, - 'id_plus_six': self.a1.id + 6, - 'id_plus_seven': self.a1.id + 7, - 'id_plus_eight': self.a1.id + 8, - }], transform=identity) - # However, an exception FieldDoesNotExist will be thrown if you specify - # a non-existent field name in values() (a field that is neither in the - # model nor in extra(select)). - self.assertRaises(FieldError, - Article.objects.extra(select={'id_plus_one': 'id + 1'}).values, - 'id', 'id_plus_two') - # If you don't specify field names to values(), all are returned. - self.assertQuerysetEqual(Article.objects.filter(id=self.a5.id).values(), - [{ - 'id': self.a5.id, - 'headline': 'Article 5', - 'pub_date': datetime(2005, 8, 1, 9, 0) - }], transform=identity) - - def test_values_list(self): - # values_list() is similar to values(), except that the results are - # returned as a list of tuples, rather than a list of dictionaries. - # Within each tuple, the order of the elemnts is the same as the order - # of fields in the values_list() call. - identity = lambda x:x - self.assertQuerysetEqual(Article.objects.values_list('headline'), - [ - (u'Article 5',), - (u'Article 6',), - (u'Article 4',), - (u'Article 2',), - (u'Article 3',), - (u'Article 7',), - (u'Article 1',), - ], transform=identity) - self.assertQuerysetEqual(Article.objects.values_list('id').order_by('id'), - [(self.a1.id,), (self.a2.id,), (self.a3.id,), (self.a4.id,), (self.a5.id,), (self.a6.id,), (self.a7.id,)], - transform=identity) - self.assertQuerysetEqual( - Article.objects.values_list('id', flat=True).order_by('id'), - [self.a1.id, self.a2.id, self.a3.id, self.a4.id, self.a5.id, self.a6.id, self.a7.id], - transform=identity) - self.assertQuerysetEqual( - Article.objects.extra(select={'id_plus_one': 'id+1'}) - .order_by('id').values_list('id'), - [(self.a1.id,), (self.a2.id,), (self.a3.id,), (self.a4.id,), (self.a5.id,), (self.a6.id,), (self.a7.id,)], - transform=identity) - self.assertQuerysetEqual( - Article.objects.extra(select={'id_plus_one': 'id+1'}) - .order_by('id').values_list('id_plus_one', 'id'), - [ - (self.a1.id+1, self.a1.id), - (self.a2.id+1, self.a2.id), - (self.a3.id+1, self.a3.id), - (self.a4.id+1, self.a4.id), - (self.a5.id+1, self.a5.id), - (self.a6.id+1, self.a6.id), - (self.a7.id+1, self.a7.id) - ], - transform=identity) - self.assertQuerysetEqual( - Article.objects.extra(select={'id_plus_one': 'id+1'}) - .order_by('id').values_list('id', 'id_plus_one'), - [ - (self.a1.id, self.a1.id+1), - (self.a2.id, self.a2.id+1), - (self.a3.id, self.a3.id+1), - (self.a4.id, self.a4.id+1), - (self.a5.id, self.a5.id+1), - (self.a6.id, self.a6.id+1), - (self.a7.id, self.a7.id+1) - ], - transform=identity) - self.assertRaises(TypeError, Article.objects.values_list, 'id', 'headline', flat=True) - - def test_get_next_previous_by(self): - # Every DateField and DateTimeField creates get_next_by_FOO() and - # get_previous_by_FOO() methods. In the case of identical date values, - # these methods will use the ID as a fallback check. This guarantees - # that no records are skipped or duplicated. - self.assertEqual(repr(self.a1.get_next_by_pub_date()), - '<Article: Article 2>') - self.assertEqual(repr(self.a2.get_next_by_pub_date()), - '<Article: Article 3>') - self.assertEqual(repr(self.a2.get_next_by_pub_date(headline__endswith='6')), - '<Article: Article 6>') - self.assertEqual(repr(self.a3.get_next_by_pub_date()), - '<Article: Article 7>') - self.assertEqual(repr(self.a4.get_next_by_pub_date()), - '<Article: Article 6>') - self.assertRaises(Article.DoesNotExist, self.a5.get_next_by_pub_date) - self.assertEqual(repr(self.a6.get_next_by_pub_date()), - '<Article: Article 5>') - self.assertEqual(repr(self.a7.get_next_by_pub_date()), - '<Article: Article 4>') - - self.assertEqual(repr(self.a7.get_previous_by_pub_date()), - '<Article: Article 3>') - self.assertEqual(repr(self.a6.get_previous_by_pub_date()), - '<Article: Article 4>') - self.assertEqual(repr(self.a5.get_previous_by_pub_date()), - '<Article: Article 6>') - self.assertEqual(repr(self.a4.get_previous_by_pub_date()), - '<Article: Article 7>') - self.assertEqual(repr(self.a3.get_previous_by_pub_date()), - '<Article: Article 2>') - self.assertEqual(repr(self.a2.get_previous_by_pub_date()), - '<Article: Article 1>') - - def test_escaping(self): - # Underscores, percent signs and backslashes have special meaning in the - # underlying SQL code, but Django handles the quoting of them automatically. - a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20)) - a8.save() - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article'), - [ - '<Article: Article_ with underscore>', - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article_'), - ['<Article: Article_ with underscore>']) - a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)) - a9.save() - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article'), - [ - '<Article: Article% with percent sign>', - '<Article: Article_ with underscore>', - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='Article%'), - ['<Article: Article% with percent sign>']) - a10 = Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22)) - a10.save() - self.assertQuerysetEqual(Article.objects.filter(headline__contains='\\'), - ['<Article: Article with \ backslash>']) - - def test_exclude(self): - a8 = Article.objects.create(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20)) - a9 = Article.objects.create(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)) - a10 = Article.objects.create(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22)) - - # exclude() is the opposite of filter() when doing lookups: - self.assertQuerysetEqual( - Article.objects.filter(headline__contains='Article').exclude(headline__contains='with'), - [ - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - self.assertQuerysetEqual(Article.objects.exclude(headline__startswith="Article_"), - [ - '<Article: Article with \\ backslash>', - '<Article: Article% with percent sign>', - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - self.assertQuerysetEqual(Article.objects.exclude(headline="Article 7"), - [ - '<Article: Article with \\ backslash>', - '<Article: Article% with percent sign>', - '<Article: Article_ with underscore>', - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 1>', - ]) - - def test_none(self): - # none() returns an EmptyQuerySet that behaves like any other QuerySet object - self.assertQuerysetEqual(Article.objects.none(), []) - self.assertQuerysetEqual( - Article.objects.none().filter(headline__startswith='Article'), []) - self.assertQuerysetEqual( - Article.objects.filter(headline__startswith='Article').none(), []) - self.assertEqual(Article.objects.none().count(), 0) - self.assertEqual( - Article.objects.none().update(headline="This should not take effect"), 0) - self.assertQuerysetEqual( - [article for article in Article.objects.none().iterator()], - []) - - def test_in(self): - # using __in with an empty list should return an empty query set - self.assertQuerysetEqual(Article.objects.filter(id__in=[]), []) - self.assertQuerysetEqual(Article.objects.exclude(id__in=[]), - [ - '<Article: Article 5>', - '<Article: Article 6>', - '<Article: Article 4>', - '<Article: Article 2>', - '<Article: Article 3>', - '<Article: Article 7>', - '<Article: Article 1>', - ]) - - def test_error_messages(self): - # Programming errors are pointed out with nice error messages - try: - Article.objects.filter(pub_date_year='2005').count() - self.fail('FieldError not raised') - except FieldError, ex: - self.assertEqual(str(ex), "Cannot resolve keyword 'pub_date_year' " - "into field. Choices are: headline, id, pub_date") - try: - Article.objects.filter(headline__starts='Article') - self.fail('FieldError not raised') - except FieldError, ex: - self.assertEqual(str(ex), "Join on field 'headline' not permitted. " - "Did you misspell 'starts' for the lookup type?") - - def test_regex(self): - # Create some articles with a bit more interesting headlines for testing field lookups: - for a in Article.objects.all(): - a.delete() - now = datetime.now() - a1 = Article(pub_date=now, headline='f') - a1.save() - a2 = Article(pub_date=now, headline='fo') - a2.save() - a3 = Article(pub_date=now, headline='foo') - a3.save() - a4 = Article(pub_date=now, headline='fooo') - a4.save() - a5 = Article(pub_date=now, headline='hey-Foo') - a5.save() - a6 = Article(pub_date=now, headline='bar') - a6.save() - a7 = Article(pub_date=now, headline='AbBa') - a7.save() - a8 = Article(pub_date=now, headline='baz') - a8.save() - a9 = Article(pub_date=now, headline='baxZ') - a9.save() - # zero-or-more - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fo*'), - ['<Article: f>', '<Article: fo>', '<Article: foo>', '<Article: fooo>']) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'fo*'), - [ - '<Article: f>', - '<Article: fo>', - '<Article: foo>', - '<Article: fooo>', - '<Article: hey-Foo>', - ]) - # one-or-more - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fo+'), - ['<Article: fo>', '<Article: foo>', '<Article: fooo>']) - # wildcard - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'fooo?'), - ['<Article: foo>', '<Article: fooo>']) - # leading anchor - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'^b'), - ['<Article: bar>', '<Article: baxZ>', '<Article: baz>']) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'^a'), - ['<Article: AbBa>']) - # trailing anchor - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'z$'), - ['<Article: baz>']) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'z$'), - ['<Article: baxZ>', '<Article: baz>']) - # character sets - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'ba[rz]'), - ['<Article: bar>', '<Article: baz>']) - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'ba.[RxZ]'), - ['<Article: baxZ>']) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'ba[RxZ]'), - ['<Article: bar>', '<Article: baxZ>', '<Article: baz>']) - - # and more articles: - a10 = Article(pub_date=now, headline='foobar') - a10.save() - a11 = Article(pub_date=now, headline='foobaz') - a11.save() - a12 = Article(pub_date=now, headline='ooF') - a12.save() - a13 = Article(pub_date=now, headline='foobarbaz') - a13.save() - a14 = Article(pub_date=now, headline='zoocarfaz') - a14.save() - a15 = Article(pub_date=now, headline='barfoobaz') - a15.save() - a16 = Article(pub_date=now, headline='bazbaRFOO') - a16.save() - - # alternation - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'oo(f|b)'), - [ - '<Article: barfoobaz>', - '<Article: foobar>', - '<Article: foobarbaz>', - '<Article: foobaz>', - ]) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'oo(f|b)'), - [ - '<Article: barfoobaz>', - '<Article: foobar>', - '<Article: foobarbaz>', - '<Article: foobaz>', - '<Article: ooF>', - ]) - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'^foo(f|b)'), - ['<Article: foobar>', '<Article: foobarbaz>', '<Article: foobaz>']) - - # greedy matching - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'b.*az'), - [ - '<Article: barfoobaz>', - '<Article: baz>', - '<Article: bazbaRFOO>', - '<Article: foobarbaz>', - '<Article: foobaz>', - ]) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'b.*ar'), - [ - '<Article: bar>', - '<Article: barfoobaz>', - '<Article: bazbaRFOO>', - '<Article: foobar>', - '<Article: foobarbaz>', - ]) - - if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql': - def test_regex_backreferencing(self): - # grouping and backreferences - now = datetime.now() - a10 = Article(pub_date=now, headline='foobar') - a10.save() - a11 = Article(pub_date=now, headline='foobaz') - a11.save() - a12 = Article(pub_date=now, headline='ooF') - a12.save() - a13 = Article(pub_date=now, headline='foobarbaz') - a13.save() - a14 = Article(pub_date=now, headline='zoocarfaz') - a14.save() - a15 = Article(pub_date=now, headline='barfoobaz') - a15.save() - a16 = Article(pub_date=now, headline='bazbaRFOO') - a16.save() - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'b(.).*b\1'), - ['<Article: barfoobaz>', '<Article: bazbaRFOO>', '<Article: foobarbaz>']) diff --git a/parts/django/tests/modeltests/m2m_and_m2o/__init__.py b/parts/django/tests/modeltests/m2m_and_m2o/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/m2m_and_m2o/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/m2m_and_m2o/models.py b/parts/django/tests/modeltests/m2m_and_m2o/models.py deleted file mode 100644 index 0fea1a2..0000000 --- a/parts/django/tests/modeltests/m2m_and_m2o/models.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -29. Many-to-many and many-to-one relationships to the same table - -Make sure to set ``related_name`` if you use relationships to the same table. -""" - -from django.db import models - -class User(models.Model): - username = models.CharField(max_length=20) - -class Issue(models.Model): - num = models.IntegerField() - cc = models.ManyToManyField(User, blank=True, related_name='test_issue_cc') - client = models.ForeignKey(User, related_name='test_issue_client') - - def __unicode__(self): - return unicode(self.num) - - class Meta: - ordering = ('num',) diff --git a/parts/django/tests/modeltests/m2m_and_m2o/tests.py b/parts/django/tests/modeltests/m2m_and_m2o/tests.py deleted file mode 100644 index dedf9cd..0000000 --- a/parts/django/tests/modeltests/m2m_and_m2o/tests.py +++ /dev/null @@ -1,75 +0,0 @@ -from django.db.models import Q -from django.test import TestCase - -from models import Issue, User - - -class RelatedObjectTests(TestCase): - def test_m2m_and_m2o(self): - r = User.objects.create(username="russell") - g = User.objects.create(username="gustav") - - i1 = Issue(num=1) - i1.client = r - i1.save() - - i2 = Issue(num=2) - i2.client = r - i2.save() - i2.cc.add(r) - - i3 = Issue(num=3) - i3.client = g - i3.save() - i3.cc.add(r) - - self.assertQuerysetEqual( - Issue.objects.filter(client=r.id), [ - 1, - 2, - ], - lambda i: i.num - ) - self.assertQuerysetEqual( - Issue.objects.filter(client=g.id), [ - 3, - ], - lambda i: i.num - ) - self.assertQuerysetEqual( - Issue.objects.filter(cc__id__exact=g.id), [] - ) - self.assertQuerysetEqual( - Issue.objects.filter(cc__id__exact=r.id), [ - 2, - 3, - ], - lambda i: i.num - ) - - # These queries combine results from the m2m and the m2o relationships. - # They're three ways of saying the same thing. - self.assertQuerysetEqual( - Issue.objects.filter(Q(cc__id__exact = r.id) | Q(client=r.id)), [ - 1, - 2, - 3, - ], - lambda i: i.num - ) - self.assertQuerysetEqual( - Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id), [ - 1, - 2, - 3, - ], - lambda i: i.num - ) - self.assertQuerysetEqual( - Issue.objects.filter(Q(client=r.id) | Q(cc__id__exact=r.id)), [ - 1, - 2, - 3, - ], - lambda i: i.num - ) diff --git a/parts/django/tests/modeltests/m2m_intermediary/__init__.py b/parts/django/tests/modeltests/m2m_intermediary/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/m2m_intermediary/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/m2m_intermediary/models.py b/parts/django/tests/modeltests/m2m_intermediary/models.py deleted file mode 100644 index 8042a52..0000000 --- a/parts/django/tests/modeltests/m2m_intermediary/models.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -9. Many-to-many relationships via an intermediary table - -For many-to-many relationships that need extra fields on the intermediary -table, use an intermediary model. - -In this example, an ``Article`` can have multiple ``Reporter`` objects, and -each ``Article``-``Reporter`` combination (a ``Writer``) has a ``position`` -field, which specifies the ``Reporter``'s position for the given article -(e.g. "Staff writer"). -""" - -from django.db import models - -class Reporter(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateField() - - def __unicode__(self): - return self.headline - -class Writer(models.Model): - reporter = models.ForeignKey(Reporter) - article = models.ForeignKey(Article) - position = models.CharField(max_length=100) - - def __unicode__(self): - return u'%s (%s)' % (self.reporter, self.position) - diff --git a/parts/django/tests/modeltests/m2m_intermediary/tests.py b/parts/django/tests/modeltests/m2m_intermediary/tests.py deleted file mode 100644 index 5f35741..0000000 --- a/parts/django/tests/modeltests/m2m_intermediary/tests.py +++ /dev/null @@ -1,38 +0,0 @@ -from datetime import datetime - -from django.test import TestCase - -from models import Reporter, Article, Writer - - -class M2MIntermediaryTests(TestCase): - def test_intermeiary(self): - r1 = Reporter.objects.create(first_name="John", last_name="Smith") - r2 = Reporter.objects.create(first_name="Jane", last_name="Doe") - - a = Article.objects.create( - headline="This is a test", pub_date=datetime(2005, 7, 27) - ) - - w1 = Writer.objects.create(reporter=r1, article=a, position="Main writer") - w2 = Writer.objects.create(reporter=r2, article=a, position="Contributor") - - self.assertQuerysetEqual( - a.writer_set.select_related().order_by("-position"), [ - ("John Smith", "Main writer"), - ("Jane Doe", "Contributor"), - ], - lambda w: (unicode(w.reporter), w.position) - ) - self.assertEqual(w1.reporter, r1) - self.assertEqual(w2.reporter, r2) - - self.assertEqual(w1.article, a) - self.assertEqual(w2.article, a) - - self.assertQuerysetEqual( - r1.writer_set.all(), [ - ("John Smith", "Main writer") - ], - lambda w: (unicode(w.reporter), w.position) - ) diff --git a/parts/django/tests/modeltests/m2m_multiple/__init__.py b/parts/django/tests/modeltests/m2m_multiple/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/m2m_multiple/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/m2m_multiple/models.py b/parts/django/tests/modeltests/m2m_multiple/models.py deleted file mode 100644 index e53f840..0000000 --- a/parts/django/tests/modeltests/m2m_multiple/models.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -20. Multiple many-to-many relationships between the same two tables - -In this example, an ``Article`` can have many "primary" ``Category`` objects -and many "secondary" ``Category`` objects. - -Set ``related_name`` to designate what the reverse relationship is called. -""" - -from django.db import models - -class Category(models.Model): - name = models.CharField(max_length=20) - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class Article(models.Model): - headline = models.CharField(max_length=50) - pub_date = models.DateTimeField() - primary_categories = models.ManyToManyField(Category, related_name='primary_article_set') - secondary_categories = models.ManyToManyField(Category, related_name='secondary_article_set') - class Meta: - ordering = ('pub_date',) - - def __unicode__(self): - return self.headline - diff --git a/parts/django/tests/modeltests/m2m_multiple/tests.py b/parts/django/tests/modeltests/m2m_multiple/tests.py deleted file mode 100644 index 1f4503a..0000000 --- a/parts/django/tests/modeltests/m2m_multiple/tests.py +++ /dev/null @@ -1,84 +0,0 @@ -from datetime import datetime - -from django.test import TestCase - -from models import Article, Category - - -class M2MMultipleTests(TestCase): - def test_multiple(self): - c1, c2, c3, c4 = [ - Category.objects.create(name=name) - for name in ["Sports", "News", "Crime", "Life"] - ] - - a1 = Article.objects.create( - headline="Area man steals", pub_date=datetime(2005, 11, 27) - ) - a1.primary_categories.add(c2, c3) - a1.secondary_categories.add(c4) - - a2 = Article.objects.create( - headline="Area man runs", pub_date=datetime(2005, 11, 28) - ) - a2.primary_categories.add(c1, c2) - a2.secondary_categories.add(c4) - - self.assertQuerysetEqual( - a1.primary_categories.all(), [ - "Crime", - "News", - ], - lambda c: c.name - ) - self.assertQuerysetEqual( - a2.primary_categories.all(), [ - "News", - "Sports", - ], - lambda c: c.name - ) - self.assertQuerysetEqual( - a1.secondary_categories.all(), [ - "Life", - ], - lambda c: c.name - ) - self.assertQuerysetEqual( - c1.primary_article_set.all(), [ - "Area man runs", - ], - lambda a: a.headline - ) - self.assertQuerysetEqual( - c1.secondary_article_set.all(), [] - ) - self.assertQuerysetEqual( - c2.primary_article_set.all(), [ - "Area man steals", - "Area man runs", - ], - lambda a: a.headline - ) - self.assertQuerysetEqual( - c2.secondary_article_set.all(), [] - ) - self.assertQuerysetEqual( - c3.primary_article_set.all(), [ - "Area man steals", - ], - lambda a: a.headline - ) - self.assertQuerysetEqual( - c3.secondary_article_set.all(), [] - ) - self.assertQuerysetEqual( - c4.primary_article_set.all(), [] - ) - self.assertQuerysetEqual( - c4.secondary_article_set.all(), [ - "Area man steals", - "Area man runs", - ], - lambda a: a.headline - ) diff --git a/parts/django/tests/modeltests/m2m_recursive/__init__.py b/parts/django/tests/modeltests/m2m_recursive/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/m2m_recursive/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/m2m_recursive/models.py b/parts/django/tests/modeltests/m2m_recursive/models.py deleted file mode 100644 index 83c943a..0000000 --- a/parts/django/tests/modeltests/m2m_recursive/models.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -28. Many-to-many relationships between the same two tables - -In this example, a ``Person`` can have many friends, who are also ``Person`` -objects. Friendship is a symmetrical relationship - if I am your friend, you -are my friend. Here, ``friends`` is an example of a symmetrical -``ManyToManyField``. - -A ``Person`` can also have many idols - but while I may idolize you, you may -not think the same of me. Here, ``idols`` is an example of a non-symmetrical -``ManyToManyField``. Only recursive ``ManyToManyField`` fields may be -non-symmetrical, and they are symmetrical by default. - -This test validates that the many-to-many table is created using a mangled name -if there is a name clash, and tests that symmetry is preserved where -appropriate. -""" - -from django.db import models - - -class Person(models.Model): - name = models.CharField(max_length=20) - friends = models.ManyToManyField('self') - idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers') - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/m2m_recursive/tests.py b/parts/django/tests/modeltests/m2m_recursive/tests.py deleted file mode 100644 index 4251028..0000000 --- a/parts/django/tests/modeltests/m2m_recursive/tests.py +++ /dev/null @@ -1,253 +0,0 @@ -from operator import attrgetter - -from django.test import TestCase - -from models import Person - - -class RecursiveM2MTests(TestCase): - def test_recursive_m2m(self): - a, b, c, d = [ - Person.objects.create(name=name) - for name in ["Anne", "Bill", "Chuck", "David"] - ] - - # Add some friends in the direction of field definition - # Anne is friends with Bill and Chuck - a.friends.add(b, c) - - # David is friends with Anne and Chuck - add in reverse direction - d.friends.add(a,c) - - # Who is friends with Anne? - self.assertQuerysetEqual( - a.friends.all(), [ - "Bill", - "Chuck", - "David" - ], - attrgetter("name") - ) - # Who is friends with Bill? - self.assertQuerysetEqual( - b.friends.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who is friends with Chuck? - self.assertQuerysetEqual( - c.friends.all(), [ - "Anne", - "David" - ], - attrgetter("name") - ) - # Who is friends with David? - self.assertQuerysetEqual( - d.friends.all(), [ - "Anne", - "Chuck", - ], - attrgetter("name") - ) - # Bill is already friends with Anne - add Anne again, but in the - # reverse direction - b.friends.add(a) - - # Who is friends with Anne? - self.assertQuerysetEqual( - a.friends.all(), [ - "Bill", - "Chuck", - "David", - ], - attrgetter("name") - ) - # Who is friends with Bill? - self.assertQuerysetEqual( - b.friends.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Remove Anne from Bill's friends - b.friends.remove(a) - # Who is friends with Anne? - self.assertQuerysetEqual( - a.friends.all(), [ - "Chuck", - "David", - ], - attrgetter("name") - ) - # Who is friends with Bill? - self.assertQuerysetEqual( - b.friends.all(), [] - ) - - # Clear Anne's group of friends - a.friends.clear() - # Who is friends with Anne? - self.assertQuerysetEqual( - a.friends.all(), [] - ) - # Reverse relationships should also be gone - # Who is friends with Chuck? - self.assertQuerysetEqual( - c.friends.all(), [ - "David", - ], - attrgetter("name") - ) - # Who is friends with David? - self.assertQuerysetEqual( - d.friends.all(), [ - "Chuck", - ], - attrgetter("name") - ) - - # Add some idols in the direction of field definition - # Anne idolizes Bill and Chuck - a.idols.add(b, c) - # Bill idolizes Anne right back - b.idols.add(a) - # David is idolized by Anne and Chuck - add in reverse direction - d.stalkers.add(a, c) - - # Who are Anne's idols? - self.assertQuerysetEqual( - a.idols.all(), [ - "Bill", - "Chuck", - "David", - ], - attrgetter("name") - ) - # Who is stalking Anne? - self.assertQuerysetEqual( - a.stalkers.all(), [ - "Bill", - ], - attrgetter("name") - ) - # Who are Bill's idols? - self.assertQuerysetEqual( - b.idols.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who is stalking Bill? - self.assertQuerysetEqual( - b.stalkers.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who are Chuck's idols? - self.assertQuerysetEqual( - c.idols.all(), [ - "David", - ], - attrgetter("name"), - ) - # Who is stalking Chuck? - self.assertQuerysetEqual( - c.stalkers.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who are David's idols? - self.assertQuerysetEqual( - d.idols.all(), [] - ) - # Who is stalking David - self.assertQuerysetEqual( - d.stalkers.all(), [ - "Anne", - "Chuck", - ], - attrgetter("name") - ) - # Bill is already being stalked by Anne - add Anne again, but in the - # reverse direction - b.stalkers.add(a) - # Who are Anne's idols? - self.assertQuerysetEqual( - a.idols.all(), [ - "Bill", - "Chuck", - "David", - ], - attrgetter("name") - ) - # Who is stalking Anne? - self.assertQuerysetEqual( - a.stalkers.all(), [ - "Bill", - ], - attrgetter("name") - ) - # Who are Bill's idols - self.assertQuerysetEqual( - b.idols.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who is stalking Bill? - self.assertQuerysetEqual( - b.stalkers.all(), [ - "Anne", - ], - attrgetter("name"), - ) - # Remove Anne from Bill's list of stalkers - b.stalkers.remove(a) - # Who are Anne's idols? - self.assertQuerysetEqual( - a.idols.all(), [ - "Chuck", - "David", - ], - attrgetter("name") - ) - # Who is stalking Anne? - self.assertQuerysetEqual( - a.stalkers.all(), [ - "Bill", - ], - attrgetter("name") - ) - # Who are Bill's idols? - self.assertQuerysetEqual( - b.idols.all(), [ - "Anne", - ], - attrgetter("name") - ) - # Who is stalking Bill? - self.assertQuerysetEqual( - b.stalkers.all(), [] - ) - # Clear Anne's group of idols - a.idols.clear() - # Who are Anne's idols - self.assertQuerysetEqual( - a.idols.all(), [] - ) - # Reverse relationships should also be gone - # Who is stalking Chuck? - self.assertQuerysetEqual( - c.stalkers.all(), [] - ) - # Who is friends with David? - self.assertQuerysetEqual( - d.stalkers.all(), [ - "Chuck", - ], - attrgetter("name") - ) diff --git a/parts/django/tests/modeltests/m2m_signals/__init__.py b/parts/django/tests/modeltests/m2m_signals/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/parts/django/tests/modeltests/m2m_signals/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/parts/django/tests/modeltests/m2m_signals/models.py b/parts/django/tests/modeltests/m2m_signals/models.py deleted file mode 100644 index 526c4a7..0000000 --- a/parts/django/tests/modeltests/m2m_signals/models.py +++ /dev/null @@ -1,36 +0,0 @@ -from django.db import models - - -class Part(models.Model): - name = models.CharField(max_length=20) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class Car(models.Model): - name = models.CharField(max_length=20) - default_parts = models.ManyToManyField(Part) - optional_parts = models.ManyToManyField(Part, related_name='cars_optional') - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class SportsCar(Car): - price = models.IntegerField() - -class Person(models.Model): - name = models.CharField(max_length=20) - fans = models.ManyToManyField('self', related_name='idols', symmetrical=False) - friends = models.ManyToManyField('self') - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/m2m_signals/tests.py b/parts/django/tests/modeltests/m2m_signals/tests.py deleted file mode 100644 index 9e9158f..0000000 --- a/parts/django/tests/modeltests/m2m_signals/tests.py +++ /dev/null @@ -1,427 +0,0 @@ -""" -Testing signals emitted on changing m2m relations. -""" - -from django.db import models -from django.test import TestCase - -from models import Part, Car, SportsCar, Person - - -class ManyToManySignalsTest(TestCase): - def m2m_changed_signal_receiver(self, signal, sender, **kwargs): - message = { - 'instance': kwargs['instance'], - 'action': kwargs['action'], - 'reverse': kwargs['reverse'], - 'model': kwargs['model'], - } - if kwargs['pk_set']: - message['objects'] = list( - kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - ) - self.m2m_changed_messages.append(message) - - def setUp(self): - self.m2m_changed_messages = [] - - self.vw = Car.objects.create(name='VW') - self.bmw = Car.objects.create(name='BMW') - self.toyota = Car.objects.create(name='Toyota') - self.wheelset = Part.objects.create(name='Wheelset') - self.doors = Part.objects.create(name='Doors') - self.engine = Part.objects.create(name='Engine') - self.airbag = Part.objects.create(name='Airbag') - self.sunroof = Part.objects.create(name='Sunroof') - - self.alice = Person.objects.create(name='Alice') - self.bob = Person.objects.create(name='Bob') - self.chuck = Person.objects.create(name='Chuck') - self.daisy = Person.objects.create(name='Daisy') - - def tearDown(self): - # disconnect all signal handlers - models.signals.m2m_changed.disconnect( - self.m2m_changed_signal_receiver, Car.default_parts.through - ) - models.signals.m2m_changed.disconnect( - self.m2m_changed_signal_receiver, Car.optional_parts.through - ) - models.signals.m2m_changed.disconnect( - self.m2m_changed_signal_receiver, Person.fans.through - ) - models.signals.m2m_changed.disconnect( - self.m2m_changed_signal_receiver, Person.friends.through - ) - - def test_m2m_relations_add_remove_clear(self): - expected_messages = [] - - # Install a listener on one of the two m2m relations. - models.signals.m2m_changed.connect( - self.m2m_changed_signal_receiver, Car.optional_parts.through - ) - - # Test the add, remove and clear methods on both sides of the - # many-to-many relation - - # adding a default part to our car - no signal listener installed - self.vw.default_parts.add(self.sunroof) - - # Now install a listener - models.signals.m2m_changed.connect( - self.m2m_changed_signal_receiver, Car.default_parts.through - ) - - self.vw.default_parts.add(self.wheelset, self.doors, self.engine) - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors, self.engine, self.wheelset], - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors, self.engine, self.wheelset], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # give the BMW and Toyata some doors as well - self.doors.car_set.add(self.bmw, self.toyota) - expected_messages.append({ - 'instance': self.doors, - 'action': 'pre_add', - 'reverse': True, - 'model': Car, - 'objects': [self.bmw, self.toyota], - }) - expected_messages.append({ - 'instance': self.doors, - 'action': 'post_add', - 'reverse': True, - 'model': Car, - 'objects': [self.bmw, self.toyota], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # remove the engine from the self.vw and the airbag (which is not set - # but is returned) - self.vw.default_parts.remove(self.engine, self.airbag) - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_remove', - 'reverse': False, - 'model': Part, - 'objects': [self.airbag, self.engine], - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_remove', - 'reverse': False, - 'model': Part, - 'objects': [self.airbag, self.engine], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # give the self.vw some optional parts (second relation to same model) - self.vw.optional_parts.add(self.airbag, self.sunroof) - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_add', - 'reverse': False, - 'model': Part, - 'objects': [self.airbag, self.sunroof], - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_add', - 'reverse': False, - 'model': Part, - 'objects': [self.airbag, self.sunroof], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # add airbag to all the cars (even though the self.vw already has one) - self.airbag.cars_optional.add(self.vw, self.bmw, self.toyota) - expected_messages.append({ - 'instance': self.airbag, - 'action': 'pre_add', - 'reverse': True, - 'model': Car, - 'objects': [self.bmw, self.toyota], - }) - expected_messages.append({ - 'instance': self.airbag, - 'action': 'post_add', - 'reverse': True, - 'model': Car, - 'objects': [self.bmw, self.toyota], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # remove airbag from the self.vw (reverse relation with custom - # related_name) - self.airbag.cars_optional.remove(self.vw) - expected_messages.append({ - 'instance': self.airbag, - 'action': 'pre_remove', - 'reverse': True, - 'model': Car, - 'objects': [self.vw], - }) - expected_messages.append({ - 'instance': self.airbag, - 'action': 'post_remove', - 'reverse': True, - 'model': Car, - 'objects': [self.vw], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # clear all parts of the self.vw - self.vw.default_parts.clear() - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_clear', - 'reverse': False, - 'model': Part, - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_clear', - 'reverse': False, - 'model': Part, - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # take all the doors off of cars - self.doors.car_set.clear() - expected_messages.append({ - 'instance': self.doors, - 'action': 'pre_clear', - 'reverse': True, - 'model': Car, - }) - expected_messages.append({ - 'instance': self.doors, - 'action': 'post_clear', - 'reverse': True, - 'model': Car, - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # take all the airbags off of cars (clear reverse relation with custom - # related_name) - self.airbag.cars_optional.clear() - expected_messages.append({ - 'instance': self.airbag, - 'action': 'pre_clear', - 'reverse': True, - 'model': Car, - }) - expected_messages.append({ - 'instance': self.airbag, - 'action': 'post_clear', - 'reverse': True, - 'model': Car, - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # alternative ways of setting relation: - self.vw.default_parts.create(name='Windows') - p6 = Part.objects.get(name='Windows') - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_add', - 'reverse': False, - 'model': Part, - 'objects': [p6], - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_add', - 'reverse': False, - 'model': Part, - 'objects': [p6], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # direct assignment clears the set first, then adds - self.vw.default_parts = [self.wheelset,self.doors,self.engine] - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_clear', - 'reverse': False, - 'model': Part, - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_clear', - 'reverse': False, - 'model': Part, - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'pre_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors, self.engine, self.wheelset], - }) - expected_messages.append({ - 'instance': self.vw, - 'action': 'post_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors, self.engine, self.wheelset], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - # Check that signals still work when model inheritance is involved - c4 = SportsCar.objects.create(name='Bugatti', price='1000000') - c4b = Car.objects.get(name='Bugatti') - c4.default_parts = [self.doors] - expected_messages.append({ - 'instance': c4, - 'action': 'pre_clear', - 'reverse': False, - 'model': Part, - }) - expected_messages.append({ - 'instance': c4, - 'action': 'post_clear', - 'reverse': False, - 'model': Part, - }) - expected_messages.append({ - 'instance': c4, - 'action': 'pre_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors], - }) - expected_messages.append({ - 'instance': c4, - 'action': 'post_add', - 'reverse': False, - 'model': Part, - 'objects': [self.doors], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - self.engine.car_set.add(c4) - expected_messages.append({ - 'instance': self.engine, - 'action': 'pre_add', - 'reverse': True, - 'model': Car, - 'objects': [c4b], - }) - expected_messages.append({ - 'instance': self.engine, - 'action': 'post_add', - 'reverse': True, - 'model': Car, - 'objects': [c4b], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - def test_m2m_relations_with_self(self): - expected_messages = [] - - models.signals.m2m_changed.connect( - self.m2m_changed_signal_receiver, Person.fans.through - ) - models.signals.m2m_changed.connect( - self.m2m_changed_signal_receiver, Person.friends.through - ) - - self.alice.friends = [self.bob, self.chuck] - expected_messages.append({ - 'instance': self.alice, - 'action': 'pre_clear', - 'reverse': False, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'post_clear', - 'reverse': False, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'pre_add', - 'reverse': False, - 'model': Person, - 'objects': [self.bob, self.chuck], - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'post_add', - 'reverse': False, - 'model': Person, - 'objects': [self.bob, self.chuck], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - self.alice.fans = [self.daisy] - expected_messages.append({ - 'instance': self.alice, - 'action': 'pre_clear', - 'reverse': False, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'post_clear', - 'reverse': False, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'pre_add', - 'reverse': False, - 'model': Person, - 'objects': [self.daisy], - }) - expected_messages.append({ - 'instance': self.alice, - 'action': 'post_add', - 'reverse': False, - 'model': Person, - 'objects': [self.daisy], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) - - self.chuck.idols = [self.alice,self.bob] - expected_messages.append({ - 'instance': self.chuck, - 'action': 'pre_clear', - 'reverse': True, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.chuck, - 'action': 'post_clear', - 'reverse': True, - 'model': Person, - }) - expected_messages.append({ - 'instance': self.chuck, - 'action': 'pre_add', - 'reverse': True, - 'model': Person, - 'objects': [self.alice, self.bob], - }) - expected_messages.append({ - 'instance': self.chuck, - 'action': 'post_add', - 'reverse': True, - 'model': Person, - 'objects': [self.alice, self.bob], - }) - self.assertEqual(self.m2m_changed_messages, expected_messages) diff --git a/parts/django/tests/modeltests/m2m_through/__init__.py b/parts/django/tests/modeltests/m2m_through/__init__.py deleted file mode 100644 index 139597f..0000000 --- a/parts/django/tests/modeltests/m2m_through/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/parts/django/tests/modeltests/m2m_through/models.py b/parts/django/tests/modeltests/m2m_through/models.py deleted file mode 100644 index d41fe8d..0000000 --- a/parts/django/tests/modeltests/m2m_through/models.py +++ /dev/null @@ -1,65 +0,0 @@ -from django.db import models -from datetime import datetime - -# M2M described on one of the models -class Person(models.Model): - name = models.CharField(max_length=128) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class Group(models.Model): - name = models.CharField(max_length=128) - members = models.ManyToManyField(Person, through='Membership') - custom_members = models.ManyToManyField(Person, through='CustomMembership', related_name="custom") - nodefaultsnonulls = models.ManyToManyField(Person, through='TestNoDefaultsOrNulls', related_name="testnodefaultsnonulls") - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class Membership(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - date_joined = models.DateTimeField(default=datetime.now) - invite_reason = models.CharField(max_length=64, null=True) - - class Meta: - ordering = ('date_joined', 'invite_reason', 'group') - - def __unicode__(self): - return "%s is a member of %s" % (self.person.name, self.group.name) - -class CustomMembership(models.Model): - person = models.ForeignKey(Person, db_column="custom_person_column", related_name="custom_person_related_name") - group = models.ForeignKey(Group) - weird_fk = models.ForeignKey(Membership, null=True) - date_joined = models.DateTimeField(default=datetime.now) - - def __unicode__(self): - return "%s is a member of %s" % (self.person.name, self.group.name) - - class Meta: - db_table = "test_table" - -class TestNoDefaultsOrNulls(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - nodefaultnonull = models.CharField(max_length=5) - -class PersonSelfRefM2M(models.Model): - name = models.CharField(max_length=5) - friends = models.ManyToManyField('self', through="Friendship", symmetrical=False) - - def __unicode__(self): - return self.name - -class Friendship(models.Model): - first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set") - second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set") - date_friended = models.DateTimeField() diff --git a/parts/django/tests/modeltests/m2m_through/tests.py b/parts/django/tests/modeltests/m2m_through/tests.py deleted file mode 100644 index 807e952..0000000 --- a/parts/django/tests/modeltests/m2m_through/tests.py +++ /dev/null @@ -1,343 +0,0 @@ -from datetime import datetime -from operator import attrgetter - -from django.test import TestCase - -from models import Person, Group, Membership, CustomMembership, \ - TestNoDefaultsOrNulls, PersonSelfRefM2M, Friendship - - -class M2mThroughTests(TestCase): - def setUp(self): - self.bob = Person.objects.create(name='Bob') - self.jim = Person.objects.create(name='Jim') - self.jane = Person.objects.create(name='Jane') - self.rock = Group.objects.create(name='Rock') - self.roll = Group.objects.create(name='Roll') - - def test_m2m_through(self): - # We start out by making sure that the Group 'rock' has no members. - self.assertQuerysetEqual( - self.rock.members.all(), - [] - ) - # To make Jim a member of Group Rock, simply create a Membership object. - m1 = Membership.objects.create(person=self.jim, group=self.rock) - # We can do the same for Jane and Rock. - m2 = Membership.objects.create(person=self.jane, group=self.rock) - # Let's check to make sure that it worked. Jane and Jim should be members of Rock. - self.assertQuerysetEqual( - self.rock.members.all(), [ - 'Jane', - 'Jim' - ], - attrgetter("name") - ) - # Now we can add a bunch more Membership objects to test with. - m3 = Membership.objects.create(person=self.bob, group=self.roll) - m4 = Membership.objects.create(person=self.jim, group=self.roll) - m5 = Membership.objects.create(person=self.jane, group=self.roll) - # We can get Jim's Group membership as with any ForeignKey. - self.assertQuerysetEqual( - self.jim.group_set.all(), [ - 'Rock', - 'Roll' - ], - attrgetter("name") - ) - # Querying the intermediary model works like normal. - self.assertEqual( - repr(Membership.objects.get(person=self.jane, group=self.rock)), - '<Membership: Jane is a member of Rock>' - ) - # It's not only get that works. Filter works like normal as well. - self.assertQuerysetEqual( - Membership.objects.filter(person=self.jim), [ - '<Membership: Jim is a member of Rock>', - '<Membership: Jim is a member of Roll>' - ] - ) - self.rock.members.clear() - # Now there will be no members of Rock. - self.assertQuerysetEqual( - self.rock.members.all(), - [] - ) - - - - def test_forward_descriptors(self): - # Due to complications with adding via an intermediary model, - # the add method is not provided. - self.assertRaises(AttributeError, lambda: self.rock.members.add(self.bob)) - # Create is also disabled as it suffers from the same problems as add. - self.assertRaises(AttributeError, lambda: self.rock.members.create(name='Anne')) - # Remove has similar complications, and is not provided either. - self.assertRaises(AttributeError, lambda: self.rock.members.remove(self.jim)) - - m1 = Membership.objects.create(person=self.jim, group=self.rock) - m2 = Membership.objects.create(person=self.jane, group=self.rock) - - # Here we back up the list of all members of Rock. - backup = list(self.rock.members.all()) - # ...and we verify that it has worked. - self.assertEqual( - [p.name for p in backup], - ['Jane', 'Jim'] - ) - # The clear function should still work. - self.rock.members.clear() - # Now there will be no members of Rock. - self.assertQuerysetEqual( - self.rock.members.all(), - [] - ) - - # Assignment should not work with models specifying a through model for many of - # the same reasons as adding. - self.assertRaises(AttributeError, setattr, self.rock, "members", backup) - # Let's re-save those instances that we've cleared. - m1.save() - m2.save() - # Verifying that those instances were re-saved successfully. - self.assertQuerysetEqual( - self.rock.members.all(),[ - 'Jane', - 'Jim' - ], - attrgetter("name") - ) - - def test_reverse_descriptors(self): - # Due to complications with adding via an intermediary model, - # the add method is not provided. - self.assertRaises(AttributeError, lambda: self.bob.group_set.add(self.rock)) - # Create is also disabled as it suffers from the same problems as add. - self.assertRaises(AttributeError, lambda: self.bob.group_set.create(name="funk")) - # Remove has similar complications, and is not provided either. - self.assertRaises(AttributeError, lambda: self.jim.group_set.remove(self.rock)) - - m1 = Membership.objects.create(person=self.jim, group=self.rock) - m2 = Membership.objects.create(person=self.jim, group=self.roll) - - # Here we back up the list of all of Jim's groups. - backup = list(self.jim.group_set.all()) - self.assertEqual( - [g.name for g in backup], - ['Rock', 'Roll'] - ) - # The clear function should still work. - self.jim.group_set.clear() - # Now Jim will be in no groups. - self.assertQuerysetEqual( - self.jim.group_set.all(), - [] - ) - # Assignment should not work with models specifying a through model for many of - # the same reasons as adding. - self.assertRaises(AttributeError, setattr, self.jim, "group_set", backup) - # Let's re-save those instances that we've cleared. - - m1.save() - m2.save() - # Verifying that those instances were re-saved successfully. - self.assertQuerysetEqual( - self.jim.group_set.all(),[ - 'Rock', - 'Roll' - ], - attrgetter("name") - ) - - def test_custom_tests(self): - # Let's see if we can query through our second relationship. - self.assertQuerysetEqual( - self.rock.custom_members.all(), - [] - ) - # We can query in the opposite direction as well. - self.assertQuerysetEqual( - self.bob.custom.all(), - [] - ) - - cm1 = CustomMembership.objects.create(person=self.bob, group=self.rock) - cm2 = CustomMembership.objects.create(person=self.jim, group=self.rock) - - # If we get the number of people in Rock, it should be both Bob and Jim. - self.assertQuerysetEqual( - self.rock.custom_members.all(),[ - 'Bob', - 'Jim' - ], - attrgetter("name") - ) - # Bob should only be in one custom group. - self.assertQuerysetEqual( - self.bob.custom.all(),[ - 'Rock' - ], - attrgetter("name") - ) - # Let's make sure our new descriptors don't conflict with the FK related_name. - self.assertQuerysetEqual( - self.bob.custom_person_related_name.all(),[ - '<CustomMembership: Bob is a member of Rock>' - ] - ) - - def test_self_referential_tests(self): - # Let's first create a person who has no friends. - tony = PersonSelfRefM2M.objects.create(name="Tony") - self.assertQuerysetEqual( - tony.friends.all(), - [] - ) - - chris = PersonSelfRefM2M.objects.create(name="Chris") - f = Friendship.objects.create(first=tony, second=chris, date_friended=datetime.now()) - - # Tony should now show that Chris is his friend. - self.assertQuerysetEqual( - tony.friends.all(),[ - 'Chris' - ], - attrgetter("name") - ) - # But we haven't established that Chris is Tony's Friend. - self.assertQuerysetEqual( - chris.friends.all(), - [] - ) - f2 = Friendship.objects.create(first=chris, second=tony, date_friended=datetime.now()) - - # Having added Chris as a friend, let's make sure that his friend set reflects - # that addition. - self.assertQuerysetEqual( - chris.friends.all(),[ - 'Tony' - ], - attrgetter("name") - ) - - # Chris gets mad and wants to get rid of all of his friends. - chris.friends.clear() - # Now he should not have any more friends. - self.assertQuerysetEqual( - chris.friends.all(), - [] - ) - # Since this isn't a symmetrical relation, Tony's friend link still exists. - self.assertQuerysetEqual( - tony.friends.all(),[ - 'Chris' - ], - attrgetter("name") - ) - - def test_query_tests(self): - m1 = Membership.objects.create(person=self.jim, group=self.rock) - m2 = Membership.objects.create(person=self.jane, group=self.rock) - m3 = Membership.objects.create(person=self.bob, group=self.roll) - m4 = Membership.objects.create(person=self.jim, group=self.roll) - m5 = Membership.objects.create(person=self.jane, group=self.roll) - - m2.invite_reason = "She was just awesome." - m2.date_joined = datetime(2006, 1, 1) - m2.save() - m3.date_joined = datetime(2004, 1, 1) - m3.save() - m5.date_joined = datetime(2004, 1, 1) - m5.save() - - # We can query for the related model by using its attribute name (members, in - # this case). - self.assertQuerysetEqual( - Group.objects.filter(members__name='Bob'),[ - 'Roll' - ], - attrgetter("name") - ) - - # To query through the intermediary model, we specify its model name. - # In this case, membership. - self.assertQuerysetEqual( - Group.objects.filter(membership__invite_reason="She was just awesome."),[ - 'Rock' - ], - attrgetter("name") - ) - - # If we want to query in the reverse direction by the related model, use its - # model name (group, in this case). - self.assertQuerysetEqual( - Person.objects.filter(group__name="Rock"),[ - 'Jane', - 'Jim' - ], - attrgetter("name") - ) - - cm1 = CustomMembership.objects.create(person=self.bob, group=self.rock) - cm2 = CustomMembership.objects.create(person=self.jim, group=self.rock) - # If the m2m field has specified a related_name, using that will work. - self.assertQuerysetEqual( - Person.objects.filter(custom__name="Rock"),[ - 'Bob', - 'Jim' - ], - attrgetter("name") - ) - - # To query through the intermediary model in the reverse direction, we again - # specify its model name (membership, in this case). - self.assertQuerysetEqual( - Person.objects.filter(membership__invite_reason="She was just awesome."),[ - 'Jane' - ], - attrgetter("name") - ) - - # Let's see all of the groups that Jane joined after 1 Jan 2005: - self.assertQuerysetEqual( - Group.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__person=self.jane),[ - 'Rock' - ], - attrgetter("name") - ) - - # Queries also work in the reverse direction: Now let's see all of the people - # that have joined Rock since 1 Jan 2005: - self.assertQuerysetEqual( - Person.objects.filter(membership__date_joined__gt=datetime(2005, 1, 1), membership__group=self.rock),[ - 'Jane', - 'Jim' - ], - attrgetter("name") - ) - - # Conceivably, queries through membership could return correct, but non-unique - # querysets. To demonstrate this, we query for all people who have joined a - # group after 2004: - self.assertQuerysetEqual( - Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1)),[ - 'Jane', - 'Jim', - 'Jim' - ], - attrgetter("name") - ) - - # Jim showed up twice, because he joined two groups ('Rock', and 'Roll'): - self.assertEqual( - [(m.person.name, m.group.name) for m in Membership.objects.filter(date_joined__gt=datetime(2004, 1, 1))], - [(u'Jane', u'Rock'), (u'Jim', u'Rock'), (u'Jim', u'Roll')] - ) - # QuerySet's distinct() method can correct this problem. - self.assertQuerysetEqual( - Person.objects.filter(membership__date_joined__gt=datetime(2004, 1, 1)).distinct(),[ - 'Jane', - 'Jim' - ], - attrgetter("name") - ) diff --git a/parts/django/tests/modeltests/m2o_recursive/__init__.py b/parts/django/tests/modeltests/m2o_recursive/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/m2o_recursive/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/m2o_recursive/models.py b/parts/django/tests/modeltests/m2o_recursive/models.py deleted file mode 100644 index ed9945a..0000000 --- a/parts/django/tests/modeltests/m2o_recursive/models.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -11. Relating an object to itself, many-to-one - -To define a many-to-one relationship between a model and itself, use -``ForeignKey('self')``. - -In this example, a ``Category`` is related to itself. That is, each -``Category`` has a parent ``Category``. - -Set ``related_name`` to designate what the reverse relationship is called. -""" - -from django.db import models - -class Category(models.Model): - name = models.CharField(max_length=20) - parent = models.ForeignKey('self', blank=True, null=True, related_name='child_set') - - def __unicode__(self): - return self.name - -class Person(models.Model): - full_name = models.CharField(max_length=20) - mother = models.ForeignKey('self', null=True, related_name='mothers_child_set') - father = models.ForeignKey('self', null=True, related_name='fathers_child_set') - - def __unicode__(self): - return self.full_name diff --git a/parts/django/tests/modeltests/m2o_recursive/tests.py b/parts/django/tests/modeltests/m2o_recursive/tests.py deleted file mode 100644 index 79dde8b..0000000 --- a/parts/django/tests/modeltests/m2o_recursive/tests.py +++ /dev/null @@ -1,38 +0,0 @@ -from django.test import TestCase -from models import Category, Person - -class ManyToOneRecursiveTests(TestCase): - - def setUp(self): - self.r = Category(id=None, name='Root category', parent=None) - self.r.save() - self.c = Category(id=None, name='Child category', parent=self.r) - self.c.save() - - def test_m2o_recursive(self): - self.assertQuerysetEqual(self.r.child_set.all(), - ['<Category: Child category>']) - self.assertEqual(self.r.child_set.get(name__startswith='Child').id, self.c.id) - self.assertEqual(self.r.parent, None) - self.assertQuerysetEqual(self.c.child_set.all(), []) - self.assertEqual(self.c.parent.id, self.r.id) - -class MultipleManyToOneRecursiveTests(TestCase): - - def setUp(self): - self.dad = Person(full_name='John Smith Senior', mother=None, father=None) - self.dad.save() - self.mom = Person(full_name='Jane Smith', mother=None, father=None) - self.mom.save() - self.kid = Person(full_name='John Smith Junior', mother=self.mom, father=self.dad) - self.kid.save() - - def test_m2o_recursive2(self): - self.assertEqual(self.kid.mother.id, self.mom.id) - self.assertEqual(self.kid.father.id, self.dad.id) - self.assertQuerysetEqual(self.dad.fathers_child_set.all(), - ['<Person: John Smith Junior>']) - self.assertQuerysetEqual(self.mom.mothers_child_set.all(), - ['<Person: John Smith Junior>']) - self.assertQuerysetEqual(self.kid.mothers_child_set.all(), []) - self.assertQuerysetEqual(self.kid.fathers_child_set.all(), []) diff --git a/parts/django/tests/modeltests/many_to_many/__init__.py b/parts/django/tests/modeltests/many_to_many/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/many_to_many/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/many_to_many/models.py b/parts/django/tests/modeltests/many_to_many/models.py deleted file mode 100644 index 96636da..0000000 --- a/parts/django/tests/modeltests/many_to_many/models.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -5. Many-to-many relationships - -To define a many-to-many relationship, use ``ManyToManyField()``. - -In this example, an ``Article`` can be published in multiple ``Publication`` -objects, and a ``Publication`` has multiple ``Article`` objects. -""" - -from django.db import models - -class Publication(models.Model): - title = models.CharField(max_length=30) - - def __unicode__(self): - return self.title - - class Meta: - ordering = ('title',) - -class Article(models.Model): - headline = models.CharField(max_length=100) - publications = models.ManyToManyField(Publication) - - def __unicode__(self): - return self.headline - - class Meta: - ordering = ('headline',) diff --git a/parts/django/tests/modeltests/many_to_many/tests.py b/parts/django/tests/modeltests/many_to_many/tests.py deleted file mode 100644 index 39fe581..0000000 --- a/parts/django/tests/modeltests/many_to_many/tests.py +++ /dev/null @@ -1,384 +0,0 @@ -from django.test import TestCase -from models import Article, Publication - -class ManyToManyTests(TestCase): - - def setUp(self): - # Create a couple of Publications. - self.p1 = Publication.objects.create(id=None, title='The Python Journal') - self.p2 = Publication.objects.create(id=None, title='Science News') - self.p3 = Publication.objects.create(id=None, title='Science Weekly') - self.p4 = Publication.objects.create(title='Highlights for Children') - - self.a1 = Article.objects.create(id=None, headline='Django lets you build Web apps easily') - self.a1.publications.add(self.p1) - - self.a2 = Article.objects.create(id=None, headline='NASA uses Python') - self.a2.publications.add(self.p1, self.p2, self.p3, self.p4) - - self.a3 = Article.objects.create(headline='NASA finds intelligent life on Earth') - self.a3.publications.add(self.p2) - - self.a4 = Article.objects.create(headline='Oxygen-free diet works wonders') - self.a4.publications.add(self.p2) - - def test_add(self): - # Create an Article. - a5 = Article(id=None, headline='Django lets you reate Web apps easily') - # You can't associate it with a Publication until it's been saved. - self.assertRaises(ValueError, getattr, a5, 'publications') - # Save it! - a5.save() - # Associate the Article with a Publication. - a5.publications.add(self.p1) - self.assertQuerysetEqual(a5.publications.all(), - ['<Publication: The Python Journal>']) - # Create another Article, and set it to appear in both Publications. - a6 = Article(id=None, headline='ESA uses Python') - a6.save() - a6.publications.add(self.p1, self.p2) - a6.publications.add(self.p3) - # Adding a second time is OK - a6.publications.add(self.p3) - self.assertQuerysetEqual(a6.publications.all(), - [ - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - - # Adding an object of the wrong type raises TypeError - self.assertRaises(TypeError, a6.publications.add, a5) - # Add a Publication directly via publications.add by using keyword arguments. - p4 = a6.publications.create(title='Highlights for Adults') - self.assertQuerysetEqual(a6.publications.all(), - [ - '<Publication: Highlights for Adults>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - - def test_reverse_add(self): - # Adding via the 'other' end of an m2m - a5 = Article(headline='NASA finds intelligent life on Mars') - a5.save() - self.p2.article_set.add(a5) - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA finds intelligent life on Mars>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(a5.publications.all(), - ['<Publication: Science News>']) - - # Adding via the other end using keywords - new_article = self.p2.article_set.create(headline='Carbon-free diet works wonders') - self.assertQuerysetEqual( - self.p2.article_set.all(), - [ - '<Article: Carbon-free diet works wonders>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA finds intelligent life on Mars>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - a6 = self.p2.article_set.all()[3] - self.assertQuerysetEqual(a6.publications.all(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - - def test_related_sets(self): - # Article objects have access to their related Publication objects. - self.assertQuerysetEqual(self.a1.publications.all(), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual(self.a2.publications.all(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - # Publication objects have access to their related Article objects. - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.p1.article_set.all(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual(Publication.objects.get(id=self.p4.id).article_set.all(), - ['<Article: NASA uses Python>']) - - def test_selects(self): - # We can perform kwarg queries across m2m relationships - self.assertQuerysetEqual( - Article.objects.filter(publications__id__exact=self.p1.id), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__pk=self.p1.id), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications=self.p1.id), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications=self.p1), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__title__startswith="Science"), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__title__startswith="Science").distinct(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - - # The count() function respects distinct() as well. - self.assertEqual(Article.objects.filter(publications__title__startswith="Science").count(), 4) - self.assertEqual(Article.objects.filter(publications__title__startswith="Science").distinct().count(), 3) - self.assertQuerysetEqual( - Article.objects.filter(publications__in=[self.p1.id,self.p2.id]).distinct(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__in=[self.p1.id,self.p2]).distinct(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__in=[self.p1,self.p2]).distinct(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - - # Excluding a related item works as you would expect, too (although the SQL - # involved is a little complex). - self.assertQuerysetEqual(Article.objects.exclude(publications=self.p2), - ['<Article: Django lets you build Web apps easily>']) - - def test_reverse_selects(self): - # Reverse m2m queries are supported (i.e., starting at the table that - # doesn't have a ManyToManyField). - self.assertQuerysetEqual(Publication.objects.filter(id__exact=self.p1.id), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual(Publication.objects.filter(pk=self.p1.id), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual( - Publication.objects.filter(article__headline__startswith="NASA"), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - self.assertQuerysetEqual(Publication.objects.filter(article__id__exact=self.a1.id), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual(Publication.objects.filter(article__pk=self.a1.id), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual(Publication.objects.filter(article=self.a1.id), - ['<Publication: The Python Journal>']) - self.assertQuerysetEqual(Publication.objects.filter(article=self.a1), - ['<Publication: The Python Journal>']) - - self.assertQuerysetEqual( - Publication.objects.filter(article__in=[self.a1.id,self.a2.id]).distinct(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - self.assertQuerysetEqual( - Publication.objects.filter(article__in=[self.a1.id,self.a2]).distinct(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - self.assertQuerysetEqual( - Publication.objects.filter(article__in=[self.a1,self.a2]).distinct(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - '<Publication: The Python Journal>', - ]) - - def test_delete(self): - # If we delete a Publication, its Articles won't be able to access it. - self.p1.delete() - self.assertQuerysetEqual(Publication.objects.all(), - [ - '<Publication: Highlights for Children>', - '<Publication: Science News>', - '<Publication: Science Weekly>', - ]) - self.assertQuerysetEqual(self.a1.publications.all(), []) - # If we delete an Article, its Publications won't be able to access it. - self.a2.delete() - self.assertQuerysetEqual(Article.objects.all(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: Oxygen-free diet works wonders>', - ]) - - def test_bulk_delete(self): - # Bulk delete some Publications - references to deleted publications should go - Publication.objects.filter(title__startswith='Science').delete() - self.assertQuerysetEqual(Publication.objects.all(), - [ - '<Publication: Highlights for Children>', - '<Publication: The Python Journal>', - ]) - self.assertQuerysetEqual(Article.objects.all(), - [ - '<Article: Django lets you build Web apps easily>', - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.a2.publications.all(), - [ - '<Publication: Highlights for Children>', - '<Publication: The Python Journal>', - ]) - - # Bulk delete some articles - references to deleted objects should go - q = Article.objects.filter(headline__startswith='Django') - self.assertQuerysetEqual(q, ['<Article: Django lets you build Web apps easily>']) - q.delete() - # After the delete, the QuerySet cache needs to be cleared, - # and the referenced objects should be gone - self.assertQuerysetEqual(q, []) - self.assertQuerysetEqual(self.p1.article_set.all(), - ['<Article: NASA uses Python>']) - - def test_remove(self): - # Removing publication from an article: - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.a4.publications.remove(self.p2) - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual(self.a4.publications.all(), []) - # And from the other end - self.p2.article_set.remove(self.a3) - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA uses Python>', - ]) - self.assertQuerysetEqual(self.a3.publications.all(), []) - - def test_assign(self): - # Relation sets can be assigned. Assignment clears any existing set members - self.p2.article_set = [self.a4, self.a3] - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.a4.publications.all(), - ['<Publication: Science News>']) - self.a4.publications = [self.p3.id] - self.assertQuerysetEqual(self.p2.article_set.all(), - ['<Article: NASA finds intelligent life on Earth>']) - self.assertQuerysetEqual(self.a4.publications.all(), - ['<Publication: Science Weekly>']) - - # An alternate to calling clear() is to assign the empty set - self.p2.article_set = [] - self.assertQuerysetEqual(self.p2.article_set.all(), []) - self.a4.publications = [] - self.assertQuerysetEqual(self.a4.publications.all(), []) - - def test_assign_ids(self): - # Relation sets can also be set using primary key values - self.p2.article_set = [self.a4.id, self.a3.id] - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.a4.publications.all(), - ['<Publication: Science News>']) - self.a4.publications = [self.p3.id] - self.assertQuerysetEqual(self.p2.article_set.all(), - ['<Article: NASA finds intelligent life on Earth>']) - self.assertQuerysetEqual(self.a4.publications.all(), - ['<Publication: Science Weekly>']) - - def test_clear(self): - # Relation sets can be cleared: - self.p2.article_set.clear() - self.assertQuerysetEqual(self.p2.article_set.all(), []) - self.assertQuerysetEqual(self.a4.publications.all(), []) - - # And you can clear from the other end - self.p2.article_set.add(self.a3, self.a4) - self.assertQuerysetEqual(self.p2.article_set.all(), - [ - '<Article: NASA finds intelligent life on Earth>', - '<Article: Oxygen-free diet works wonders>', - ]) - self.assertQuerysetEqual(self.a4.publications.all(), - [ - '<Publication: Science News>', - ]) - self.a4.publications.clear() - self.assertQuerysetEqual(self.a4.publications.all(), []) - self.assertQuerysetEqual(self.p2.article_set.all(), - ['<Article: NASA finds intelligent life on Earth>']) diff --git a/parts/django/tests/modeltests/many_to_one/__init__.py b/parts/django/tests/modeltests/many_to_one/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/many_to_one/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/many_to_one/models.py b/parts/django/tests/modeltests/many_to_one/models.py deleted file mode 100644 index b4a0f37..0000000 --- a/parts/django/tests/modeltests/many_to_one/models.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -4. Many-to-one relationships - -To define a many-to-one relationship, use ``ForeignKey()``. -""" - -from django.db import models - -class Reporter(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - email = models.EmailField() - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateField() - reporter = models.ForeignKey(Reporter) - - def __unicode__(self): - return self.headline - - class Meta: - ordering = ('headline',) diff --git a/parts/django/tests/modeltests/many_to_one/tests.py b/parts/django/tests/modeltests/many_to_one/tests.py deleted file mode 100644 index 53306b7..0000000 --- a/parts/django/tests/modeltests/many_to_one/tests.py +++ /dev/null @@ -1,371 +0,0 @@ -from datetime import datetime -from django.test import TestCase -from django.core.exceptions import FieldError -from models import Article, Reporter - -class ManyToOneTests(TestCase): - - def setUp(self): - # Create a few Reporters. - self.r = Reporter(first_name='John', last_name='Smith', email='john@example.com') - self.r.save() - self.r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com') - self.r2.save() - # Create an Article. - self.a = Article(id=None, headline="This is a test", - pub_date=datetime(2005, 7, 27), reporter=self.r) - self.a.save() - - def test_get(self): - # Article objects have access to their related Reporter objects. - r = self.a.reporter - self.assertEqual(r.id, self.r.id) - # These are strings instead of unicode strings because that's what was used in - # the creation of this reporter (and we haven't refreshed the data from the - # database, which always returns unicode strings). - self.assertEqual((r.first_name, self.r.last_name), ('John', 'Smith')) - - def test_create(self): - # You can also instantiate an Article by passing the Reporter's ID - # instead of a Reporter object. - a3 = Article(id=None, headline="Third article", - pub_date=datetime(2005, 7, 27), reporter_id=self.r.id) - a3.save() - self.assertEqual(a3.reporter.id, self.r.id) - - # Similarly, the reporter ID can be a string. - a4 = Article(id=None, headline="Fourth article", - pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id)) - a4.save() - self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>") - - def test_add(self): - # Create an Article via the Reporter object. - new_article = self.r.article_set.create(headline="John's second story", - pub_date=datetime(2005, 7, 29)) - self.assertEqual(repr(new_article), "<Article: John's second story>") - self.assertEqual(new_article.reporter.id, self.r.id) - - # Create a new article, and add it to the article set. - new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17)) - self.r.article_set.add(new_article2) - self.assertEqual(new_article2.reporter.id, self.r.id) - self.assertQuerysetEqual(self.r.article_set.all(), - [ - "<Article: John's second story>", - "<Article: Paul's story>", - "<Article: This is a test>", - ]) - - # Add the same article to a different article set - check that it moves. - self.r2.article_set.add(new_article2) - self.assertEqual(new_article2.reporter.id, self.r2.id) - self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"]) - - # Adding an object of the wrong type raises TypeError. - self.assertRaises(TypeError, self.r.article_set.add, self.r2) - self.assertQuerysetEqual(self.r.article_set.all(), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - - def test_assign(self): - new_article = self.r.article_set.create(headline="John's second story", - pub_date=datetime(2005, 7, 29)) - new_article2 = self.r2.article_set.create(headline="Paul's story", - pub_date=datetime(2006, 1, 17)) - # Assign the article to the reporter directly using the descriptor. - new_article2.reporter = self.r - new_article2.save() - self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>") - self.assertEqual(new_article2.reporter.id, self.r.id) - self.assertQuerysetEqual(self.r.article_set.all(), [ - "<Article: John's second story>", - "<Article: Paul's story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual(self.r2.article_set.all(), []) - # Set the article back again using set descriptor. - self.r2.article_set = [new_article, new_article2] - self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: This is a test>"]) - self.assertQuerysetEqual(self.r2.article_set.all(), - [ - "<Article: John's second story>", - "<Article: Paul's story>", - ]) - - # Funny case - assignment notation can only go so far; because the - # ForeignKey cannot be null, existing members of the set must remain. - self.r.article_set = [new_article] - self.assertQuerysetEqual(self.r.article_set.all(), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"]) - # Reporter cannot be null - there should not be a clear or remove method - self.assertFalse(hasattr(self.r2.article_set, 'remove')) - self.assertFalse(hasattr(self.r2.article_set, 'clear')) - - def test_selects(self): - new_article = self.r.article_set.create(headline="John's second story", - pub_date=datetime(2005, 7, 29)) - new_article2 = self.r2.article_set.create(headline="Paul's story", - pub_date=datetime(2006, 1, 17)) - # Reporter objects have access to their related Article objects. - self.assertQuerysetEqual(self.r.article_set.all(), [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='This'), - ["<Article: This is a test>"]) - self.assertEqual(self.r.article_set.count(), 2) - self.assertEqual(self.r2.article_set.count(), 1) - # Get articles by id - self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id), - ["<Article: This is a test>"]) - self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id), - ["<Article: This is a test>"]) - # Query on an article property - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='This'), - ["<Article: This is a test>"]) - # The API automatically follows relationships as far as you need. - # Use double underscores to separate relationships. - # This works as many levels deep as you want. There's no limit. - # Find all Articles for any Reporter whose first name is "John". - self.assertQuerysetEqual(Article.objects.filter(reporter__first_name__exact='John'), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # Check that implied __exact also works - self.assertQuerysetEqual(Article.objects.filter(reporter__first_name='John'), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # Query twice over the related field. - self.assertQuerysetEqual( - Article.objects.filter(reporter__first_name__exact='John', - reporter__last_name__exact='Smith'), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # The underlying query only makes one join when a related table is referenced twice. - queryset = Article.objects.filter(reporter__first_name__exact='John', - reporter__last_name__exact='Smith') - self.assertEqual(queryset.query.get_compiler(queryset.db).as_sql()[0].count('INNER JOIN'), 1) - - # The automatically joined table has a predictable name. - self.assertQuerysetEqual( - Article.objects.filter(reporter__first_name__exact='John').extra( - where=["many_to_one_reporter.last_name='Smith'"]), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # ... and should work fine with the unicode that comes out of forms.Form.cleaned_data - self.assertQuerysetEqual( - Article.objects.filter(reporter__first_name__exact='John' - ).extra(where=["many_to_one_reporter.last_name='%s'" % u'Smith']), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # Find all Articles for a Reporter. - # Use direct ID check, pk check, and object comparison - self.assertQuerysetEqual( - Article.objects.filter(reporter__id__exact=self.r.id), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual( - Article.objects.filter(reporter__pk=self.r.id), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual( - Article.objects.filter(reporter=self.r.id), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual( - Article.objects.filter(reporter=self.r), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual( - Article.objects.filter(reporter__in=[self.r.id,self.r2.id]).distinct(), - [ - "<Article: John's second story>", - "<Article: Paul's story>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual( - Article.objects.filter(reporter__in=[self.r,self.r2]).distinct(), - [ - "<Article: John's second story>", - "<Article: Paul's story>", - "<Article: This is a test>", - ]) - # You can also use a queryset instead of a literal list of instances. - # The queryset must be reduced to a list of values using values(), - # then converted into a query - self.assertQuerysetEqual( - Article.objects.filter( - reporter__in=Reporter.objects.filter(first_name='John').values('pk').query - ).distinct(), - [ - "<Article: John's second story>", - "<Article: This is a test>", - ]) - # You need two underscores between "reporter" and "id" -- not one. - self.assertRaises(FieldError, Article.objects.filter, reporter_id__exact=self.r.id) - # You need to specify a comparison clause - self.assertRaises(FieldError, Article.objects.filter, reporter_id=self.r.id) - - def test_reverse_selects(self): - a3 = Article.objects.create(id=None, headline="Third article", - pub_date=datetime(2005, 7, 27), reporter_id=self.r.id) - a4 = Article.objects.create(id=None, headline="Fourth article", - pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id)) - # Reporters can be queried - self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual(Reporter.objects.filter(first_name__startswith='John'), - ["<Reporter: John Smith>"]) - # Reporters can query in opposite direction of ForeignKey definition - self.assertQuerysetEqual(Reporter.objects.filter(article__id__exact=self.a.id), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual(Reporter.objects.filter(article__pk=self.a.id), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual(Reporter.objects.filter(article=self.a), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__in=[self.a.id,a3.id]).distinct(), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__in=[self.a.id,a3]).distinct(), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__in=[self.a,a3]).distinct(), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__headline__startswith='T'), - ["<Reporter: John Smith>", "<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__headline__startswith='T').distinct(), - ["<Reporter: John Smith>"]) - - # Counting in the opposite direction works in conjunction with distinct() - self.assertEqual( - Reporter.objects.filter(article__headline__startswith='T').count(), 2) - self.assertEqual( - Reporter.objects.filter(article__headline__startswith='T').distinct().count(), 1) - - # Queries can go round in circles. - self.assertQuerysetEqual( - Reporter.objects.filter(article__reporter__first_name__startswith='John'), - [ - "<Reporter: John Smith>", - "<Reporter: John Smith>", - "<Reporter: John Smith>", - ]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(), - ["<Reporter: John Smith>"]) - self.assertQuerysetEqual( - Reporter.objects.filter(article__reporter__exact=self.r).distinct(), - ["<Reporter: John Smith>"]) - - # Check that implied __exact also works. - self.assertQuerysetEqual( - Reporter.objects.filter(article__reporter=self.r).distinct(), - ["<Reporter: John Smith>"]) - - # It's possible to use values() calls across many-to-one relations. - # (Note, too, that we clear the ordering here so as not to drag the - # 'headline' field into the columns being used to determine uniqueness) - d = {'reporter__first_name': u'John', 'reporter__last_name': u'Smith'} - self.assertEqual([d], - list(Article.objects.filter(reporter=self.r).distinct().order_by() - .values('reporter__first_name', 'reporter__last_name'))) - - def test_select_related(self): - # Check that Article.objects.select_related().dates() works properly when - # there are multiple Articles with the same date but different foreign-key - # objects (Reporters). - r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='royko@suntimes.com') - r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='jkass@tribune.com') - a1 = Article.objects.create(headline='First', pub_date=datetime(1980, 4, 23), reporter=r1) - a2 = Article.objects.create(headline='Second', pub_date=datetime(1980, 4, 23), reporter=r2) - self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'day')), - [ - datetime(1980, 4, 23, 0, 0), - datetime(2005, 7, 27, 0, 0), - ]) - self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'month')), - [ - datetime(1980, 4, 1, 0, 0), - datetime(2005, 7, 1, 0, 0), - ]) - self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'year')), - [ - datetime(1980, 1, 1, 0, 0), - datetime(2005, 1, 1, 0, 0), - ]) - - def test_delete(self): - new_article = self.r.article_set.create(headline="John's second story", - pub_date=datetime(2005, 7, 29)) - new_article2 = self.r2.article_set.create(headline="Paul's story", - pub_date=datetime(2006, 1, 17)) - a3 = Article.objects.create(id=None, headline="Third article", - pub_date=datetime(2005, 7, 27), reporter_id=self.r.id) - a4 = Article.objects.create(id=None, headline="Fourth article", - pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id)) - # If you delete a reporter, his articles will be deleted. - self.assertQuerysetEqual(Article.objects.all(), - [ - "<Article: Fourth article>", - "<Article: John's second story>", - "<Article: Paul's story>", - "<Article: Third article>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual(Reporter.objects.order_by('first_name'), - [ - "<Reporter: John Smith>", - "<Reporter: Paul Jones>", - ]) - self.r2.delete() - self.assertQuerysetEqual(Article.objects.all(), - [ - "<Article: Fourth article>", - "<Article: John's second story>", - "<Article: Third article>", - "<Article: This is a test>", - ]) - self.assertQuerysetEqual(Reporter.objects.order_by('first_name'), - ["<Reporter: John Smith>"]) - # You can delete using a JOIN in the query. - Reporter.objects.filter(article__headline__startswith='This').delete() - self.assertQuerysetEqual(Reporter.objects.all(), []) - self.assertQuerysetEqual(Article.objects.all(), []) - - def test_regression_12876(self): - # Regression for #12876 -- Model methods that include queries that - # recursive don't cause recursion depth problems under deepcopy. - self.r.cached_query = Article.objects.filter(reporter=self.r) - from copy import deepcopy - self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>") diff --git a/parts/django/tests/modeltests/many_to_one_null/__init__.py b/parts/django/tests/modeltests/many_to_one_null/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/many_to_one_null/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/many_to_one_null/models.py b/parts/django/tests/modeltests/many_to_one_null/models.py deleted file mode 100644 index 5f824b4..0000000 --- a/parts/django/tests/modeltests/many_to_one_null/models.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -16. Many-to-one relationships that can be null - -To define a many-to-one relationship that can have a null foreign key, use -``ForeignKey()`` with ``null=True`` . -""" - -from django.db import models - -class Reporter(models.Model): - name = models.CharField(max_length=30) - - def __unicode__(self): - return self.name - -class Article(models.Model): - headline = models.CharField(max_length=100) - reporter = models.ForeignKey(Reporter, null=True) - - class Meta: - ordering = ('headline',) - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/many_to_one_null/tests.py b/parts/django/tests/modeltests/many_to_one_null/tests.py deleted file mode 100644 index c78f980..0000000 --- a/parts/django/tests/modeltests/many_to_one_null/tests.py +++ /dev/null @@ -1,84 +0,0 @@ -from django.test import TestCase -from models import Reporter, Article - -class ManyToOneNullTests(TestCase): - - def setUp(self): - # Create a Reporter. - self.r = Reporter(name='John Smith') - self.r.save() - # Create an Article. - self.a = Article(headline="First", reporter=self.r) - self.a.save() - # Create an Article via the Reporter object. - self.a2 = self.r.article_set.create(headline="Second") - # Create an Article with no Reporter by passing "reporter=None". - self.a3 = Article(headline="Third", reporter=None) - self.a3.save() - # Create another article and reporter - self.r2 = Reporter(name='Paul Jones') - self.r2.save() - self.a4 = self.r2.article_set.create(headline='Fourth') - - def test_get_related(self): - self.assertEqual(self.a.reporter.id, self.r.id) - # Article objects have access to their related Reporter objects. - r = self.a.reporter - self.assertEqual(r.id, self.r.id) - - def test_created_via_related_set(self): - self.assertEqual(self.a2.reporter.id, self.r.id) - - def test_related_set(self): - # Reporter objects have access to their related Article objects. - self.assertQuerysetEqual(self.r.article_set.all(), - ['<Article: First>', '<Article: Second>']) - self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='Fir'), - ['<Article: First>']) - self.assertEqual(self.r.article_set.count(), 2) - - def test_created_without_related(self): - self.assertEqual(self.a3.reporter, None) - # Need to reget a3 to refresh the cache - a3 = Article.objects.get(pk=self.a3.pk) - self.assertRaises(AttributeError, getattr, a3.reporter, 'id') - # Accessing an article's 'reporter' attribute returns None - # if the reporter is set to None. - self.assertEqual(a3.reporter, None) - # To retrieve the articles with no reporters set, use "reporter__isnull=True". - self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), - ['<Article: Third>']) - # We can achieve the same thing by filtering for the case where the - # reporter is None. - self.assertQuerysetEqual(Article.objects.filter(reporter=None), - ['<Article: Third>']) - # Set the reporter for the Third article - self.assertQuerysetEqual(self.r.article_set.all(), - ['<Article: First>', '<Article: Second>']) - self.r.article_set.add(a3) - self.assertQuerysetEqual(self.r.article_set.all(), - ['<Article: First>', '<Article: Second>', '<Article: Third>']) - # Remove an article from the set, and check that it was removed. - self.r.article_set.remove(a3) - self.assertQuerysetEqual(self.r.article_set.all(), - ['<Article: First>', '<Article: Second>']) - self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), - ['<Article: Third>']) - - def test_remove_from_wrong_set(self): - self.assertQuerysetEqual(self.r2.article_set.all(), ['<Article: Fourth>']) - # Try to remove a4 from a set it does not belong to - self.assertRaises(Reporter.DoesNotExist, self.r.article_set.remove, self.a4) - self.assertQuerysetEqual(self.r2.article_set.all(), ['<Article: Fourth>']) - - def test_assign_clear_related_set(self): - # Use descriptor assignment to allocate ForeignKey. Null is legal, so - # existing members of set that are not in the assignment set are set null - self.r2.article_set = [self.a2, self.a3] - self.assertQuerysetEqual(self.r2.article_set.all(), - ['<Article: Second>', '<Article: Third>']) - # Clear the rest of the set - self.r.article_set.clear() - self.assertQuerysetEqual(self.r.article_set.all(), []) - self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), - ['<Article: First>', '<Article: Fourth>']) diff --git a/parts/django/tests/modeltests/model_forms/__init__.py b/parts/django/tests/modeltests/model_forms/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/model_forms/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/model_forms/mforms.py b/parts/django/tests/modeltests/model_forms/mforms.py deleted file mode 100644 index aef763e..0000000 --- a/parts/django/tests/modeltests/model_forms/mforms.py +++ /dev/null @@ -1,39 +0,0 @@ -from django import forms -from django.forms import ModelForm - -from models import Product, Price, Book, DerivedBook, ExplicitPK, Post, DerivedPost, Writer - -class ProductForm(ModelForm): - class Meta: - model = Product - -class PriceForm(ModelForm): - class Meta: - model = Price - -class BookForm(ModelForm): - class Meta: - model = Book - -class DerivedBookForm(ModelForm): - class Meta: - model = DerivedBook - -class ExplicitPKForm(ModelForm): - class Meta: - model = ExplicitPK - fields = ('key', 'desc',) - -class PostForm(ModelForm): - class Meta: - model = Post - -class DerivedPostForm(ModelForm): - class Meta: - model = DerivedPost - -class CustomWriterForm(ModelForm): - name = forms.CharField(required=False) - - class Meta: - model = Writer diff --git a/parts/django/tests/modeltests/model_forms/models.py b/parts/django/tests/modeltests/model_forms/models.py deleted file mode 100644 index 1087cf8..0000000 --- a/parts/django/tests/modeltests/model_forms/models.py +++ /dev/null @@ -1,1575 +0,0 @@ -""" -XX. Generating HTML forms from models - -This is mostly just a reworking of the ``form_for_model``/``form_for_instance`` -tests to use ``ModelForm``. As such, the text may not make sense in all cases, -and the examples are probably a poor fit for the ``ModelForm`` syntax. In other -words, most of these tests should be rewritten. -""" - -import os -import tempfile - -from django.db import models -from django.core.files.storage import FileSystemStorage - -temp_storage_dir = tempfile.mkdtemp() -temp_storage = FileSystemStorage(temp_storage_dir) - -ARTICLE_STATUS = ( - (1, 'Draft'), - (2, 'Pending'), - (3, 'Live'), -) - -ARTICLE_STATUS_CHAR = ( - ('d', 'Draft'), - ('p', 'Pending'), - ('l', 'Live'), -) - -class Category(models.Model): - name = models.CharField(max_length=20) - slug = models.SlugField(max_length=20) - url = models.CharField('The URL', max_length=40) - - def __unicode__(self): - return self.name - -class Writer(models.Model): - name = models.CharField(max_length=50, help_text='Use both first and last names.') - - def __unicode__(self): - return self.name - -class Article(models.Model): - headline = models.CharField(max_length=50) - slug = models.SlugField() - pub_date = models.DateField() - created = models.DateField(editable=False) - writer = models.ForeignKey(Writer) - article = models.TextField() - categories = models.ManyToManyField(Category, blank=True) - status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True) - - def save(self): - import datetime - if not self.id: - self.created = datetime.date.today() - return super(Article, self).save() - - def __unicode__(self): - return self.headline - -class ImprovedArticle(models.Model): - article = models.OneToOneField(Article) - -class ImprovedArticleWithParentLink(models.Model): - article = models.OneToOneField(Article, parent_link=True) - -class BetterWriter(Writer): - score = models.IntegerField() - -class WriterProfile(models.Model): - writer = models.OneToOneField(Writer, primary_key=True) - age = models.PositiveIntegerField() - - def __unicode__(self): - return "%s is %s" % (self.writer, self.age) - -from django.contrib.localflavor.us.models import PhoneNumberField -class PhoneNumber(models.Model): - phone = PhoneNumberField() - description = models.CharField(max_length=20) - - def __unicode__(self): - return self.phone - -class TextFile(models.Model): - description = models.CharField(max_length=20) - file = models.FileField(storage=temp_storage, upload_to='tests', max_length=15) - - def __unicode__(self): - return self.description - -try: - # If PIL is available, try testing ImageFields. Checking for the existence - # of Image is enough for CPython, but for PyPy, you need to check for the - # underlying modules If PIL is not available, ImageField tests are omitted. - # Try to import PIL in either of the two ways it can end up installed. - try: - from PIL import Image, _imaging - except ImportError: - import Image, _imaging - - test_images = True - - class ImageFile(models.Model): - def custom_upload_path(self, filename): - path = self.path or 'tests' - return '%s/%s' % (path, filename) - - description = models.CharField(max_length=20) - - # Deliberately put the image field *after* the width/height fields to - # trigger the bug in #10404 with width/height not getting assigned. - width = models.IntegerField(editable=False) - height = models.IntegerField(editable=False) - image = models.ImageField(storage=temp_storage, upload_to=custom_upload_path, - width_field='width', height_field='height') - path = models.CharField(max_length=16, blank=True, default='') - - def __unicode__(self): - return self.description - - class OptionalImageFile(models.Model): - def custom_upload_path(self, filename): - path = self.path or 'tests' - return '%s/%s' % (path, filename) - - description = models.CharField(max_length=20) - image = models.ImageField(storage=temp_storage, upload_to=custom_upload_path, - width_field='width', height_field='height', - blank=True, null=True) - width = models.IntegerField(editable=False, null=True) - height = models.IntegerField(editable=False, null=True) - path = models.CharField(max_length=16, blank=True, default='') - - def __unicode__(self): - return self.description -except ImportError: - test_images = False - -class CommaSeparatedInteger(models.Model): - field = models.CommaSeparatedIntegerField(max_length=20) - - def __unicode__(self): - return self.field - -class Product(models.Model): - slug = models.SlugField(unique=True) - - def __unicode__(self): - return self.slug - -class Price(models.Model): - price = models.DecimalField(max_digits=10, decimal_places=2) - quantity = models.PositiveIntegerField() - - def __unicode__(self): - return u"%s for %s" % (self.quantity, self.price) - - class Meta: - unique_together = (('price', 'quantity'),) - -class ArticleStatus(models.Model): - status = models.CharField(max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True) - -class Inventory(models.Model): - barcode = models.PositiveIntegerField(unique=True) - parent = models.ForeignKey('self', to_field='barcode', blank=True, null=True) - name = models.CharField(blank=False, max_length=20) - - def __unicode__(self): - return self.name - -class Book(models.Model): - title = models.CharField(max_length=40) - author = models.ForeignKey(Writer, blank=True, null=True) - special_id = models.IntegerField(blank=True, null=True, unique=True) - - class Meta: - unique_together = ('title', 'author') - -class BookXtra(models.Model): - isbn = models.CharField(max_length=16, unique=True) - suffix1 = models.IntegerField(blank=True, default=0) - suffix2 = models.IntegerField(blank=True, default=0) - - class Meta: - unique_together = (('suffix1', 'suffix2')) - abstract = True - -class DerivedBook(Book, BookXtra): - pass - -class ExplicitPK(models.Model): - key = models.CharField(max_length=20, primary_key=True) - desc = models.CharField(max_length=20, blank=True, unique=True) - class Meta: - unique_together = ('key', 'desc') - - def __unicode__(self): - return self.key - -class Post(models.Model): - title = models.CharField(max_length=50, unique_for_date='posted', blank=True) - slug = models.CharField(max_length=50, unique_for_year='posted', blank=True) - subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True) - posted = models.DateField() - - def __unicode__(self): - return self.name - -class DerivedPost(Post): - pass - -class BigInt(models.Model): - biggie = models.BigIntegerField() - - def __unicode__(self): - return unicode(self.biggie) - -class MarkupField(models.CharField): - def __init__(self, *args, **kwargs): - kwargs["max_length"] = 20 - super(MarkupField, self).__init__(*args, **kwargs) - - def formfield(self, **kwargs): - # don't allow this field to be used in form (real use-case might be - # that you know the markup will always be X, but it is among an app - # that allows the user to say it could be something else) - # regressed at r10062 - return None - -class CustomFieldForExclusionModel(models.Model): - name = models.CharField(max_length=10) - markup = MarkupField() - -__test__ = {'API_TESTS': """ ->>> from django import forms ->>> from django.forms.models import ModelForm, model_to_dict ->>> from django.core.files.uploadedfile import SimpleUploadedFile - -The bare bones, absolutely nothing custom, basic case. - ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category ->>> CategoryForm.base_fields.keys() -['name', 'slug', 'url'] - - -Extra fields. - ->>> class CategoryForm(ModelForm): -... some_extra_field = forms.BooleanField() -... -... class Meta: -... model = Category - ->>> CategoryForm.base_fields.keys() -['name', 'slug', 'url', 'some_extra_field'] - -Extra field that has a name collision with a related object accessor. - ->>> class WriterForm(ModelForm): -... book = forms.CharField(required=False) -... -... class Meta: -... model = Writer - ->>> wf = WriterForm({'name': 'Richard Lockridge'}) ->>> wf.is_valid() -True - -Replacing a field. - ->>> class CategoryForm(ModelForm): -... url = forms.BooleanField() -... -... class Meta: -... model = Category - ->>> CategoryForm.base_fields['url'].__class__ -<class 'django.forms.fields.BooleanField'> - - -Using 'fields'. - ->>> class CategoryForm(ModelForm): -... -... class Meta: -... model = Category -... fields = ['url'] - ->>> CategoryForm.base_fields.keys() -['url'] - - -Using 'exclude' - ->>> class CategoryForm(ModelForm): -... -... class Meta: -... model = Category -... exclude = ['url'] - ->>> CategoryForm.base_fields.keys() -['name', 'slug'] - - -Using 'fields' *and* 'exclude'. Not sure why you'd want to do this, but uh, -"be liberal in what you accept" and all. - ->>> class CategoryForm(ModelForm): -... -... class Meta: -... model = Category -... fields = ['name', 'url'] -... exclude = ['url'] - ->>> CategoryForm.base_fields.keys() -['name'] - -Using 'widgets' - ->>> class CategoryForm(ModelForm): -... -... class Meta: -... model = Category -... fields = ['name', 'url', 'slug'] -... widgets = { -... 'name': forms.Textarea, -... 'url': forms.TextInput(attrs={'class': 'url'}) -... } - ->>> str(CategoryForm()['name']) -'<textarea id="id_name" rows="10" cols="40" name="name"></textarea>' - ->>> str(CategoryForm()['url']) -'<input id="id_url" type="text" class="url" name="url" maxlength="40" />' - ->>> str(CategoryForm()['slug']) -'<input id="id_slug" type="text" name="slug" maxlength="20" />' - -Don't allow more than one 'model' definition in the inheritance hierarchy. -Technically, it would generate a valid form, but the fact that the resulting -save method won't deal with multiple objects is likely to trip up people not -familiar with the mechanics. - ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category - ->>> class OddForm(CategoryForm): -... class Meta: -... model = Article - -OddForm is now an Article-related thing, because BadForm.Meta overrides -CategoryForm.Meta. ->>> OddForm.base_fields.keys() -['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories'] - ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article - -First class with a Meta class wins. - ->>> class BadForm(ArticleForm, CategoryForm): -... pass ->>> OddForm.base_fields.keys() -['headline', 'slug', 'pub_date', 'writer', 'article', 'status', 'categories'] - -Subclassing without specifying a Meta on the class will use the parent's Meta -(or the first parent in the MRO if there are multiple parent classes). - ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category ->>> class SubCategoryForm(CategoryForm): -... pass ->>> SubCategoryForm.base_fields.keys() -['name', 'slug', 'url'] - -We can also subclass the Meta inner class to change the fields list. - ->>> class CategoryForm(ModelForm): -... checkbox = forms.BooleanField() -... -... class Meta: -... model = Category ->>> class SubCategoryForm(CategoryForm): -... class Meta(CategoryForm.Meta): -... exclude = ['url'] - ->>> print SubCategoryForm() -<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> -<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> -<tr><th><label for="id_checkbox">Checkbox:</label></th><td><input type="checkbox" name="checkbox" id="id_checkbox" /></td></tr> - -# test using fields to provide ordering to the fields ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category -... fields = ['url', 'name'] - ->>> CategoryForm.base_fields.keys() -['url', 'name'] - - ->>> print CategoryForm() -<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr> -<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> - ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category -... fields = ['slug', 'url', 'name'] -... exclude = ['url'] - ->>> CategoryForm.base_fields.keys() -['slug', 'name'] - -# Old form_for_x tests ####################################################### - ->>> from django.forms import ModelForm, CharField ->>> import datetime - ->>> Category.objects.all() -[] - ->>> class CategoryForm(ModelForm): -... class Meta: -... model = Category ->>> f = CategoryForm() ->>> print f -<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr> -<tr><th><label for="id_slug">Slug:</label></th><td><input id="id_slug" type="text" name="slug" maxlength="20" /></td></tr> -<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr> ->>> print f.as_ul() -<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li> -<li><label for="id_slug">Slug:</label> <input id="id_slug" type="text" name="slug" maxlength="20" /></li> -<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li> ->>> print f['name'] -<input id="id_name" type="text" name="name" maxlength="20" /> - ->>> f = CategoryForm(auto_id=False) ->>> print f.as_ul() -<li>Name: <input type="text" name="name" maxlength="20" /></li> -<li>Slug: <input type="text" name="slug" maxlength="20" /></li> -<li>The URL: <input type="text" name="url" maxlength="40" /></li> - ->>> f = CategoryForm({'name': 'Entertainment', 'slug': 'entertainment', 'url': 'entertainment'}) ->>> f.is_valid() -True ->>> f.cleaned_data['url'] -u'entertainment' ->>> f.cleaned_data['name'] -u'Entertainment' ->>> f.cleaned_data['slug'] -u'entertainment' ->>> obj = f.save() ->>> obj -<Category: Entertainment> ->>> Category.objects.all() -[<Category: Entertainment>] - ->>> f = CategoryForm({'name': "It's a test", 'slug': 'its-test', 'url': 'test'}) ->>> f.is_valid() -True ->>> f.cleaned_data['url'] -u'test' ->>> f.cleaned_data['name'] -u"It's a test" ->>> f.cleaned_data['slug'] -u'its-test' ->>> obj = f.save() ->>> obj -<Category: It's a test> ->>> Category.objects.order_by('name') -[<Category: Entertainment>, <Category: It's a test>] - -If you call save() with commit=False, then it will return an object that -hasn't yet been saved to the database. In this case, it's up to you to call -save() on the resulting model instance. ->>> f = CategoryForm({'name': 'Third test', 'slug': 'third-test', 'url': 'third'}) ->>> f.is_valid() -True ->>> f.cleaned_data['url'] -u'third' ->>> f.cleaned_data['name'] -u'Third test' ->>> f.cleaned_data['slug'] -u'third-test' ->>> obj = f.save(commit=False) ->>> obj -<Category: Third test> ->>> Category.objects.order_by('name') -[<Category: Entertainment>, <Category: It's a test>] ->>> obj.save() ->>> Category.objects.order_by('name') -[<Category: Entertainment>, <Category: It's a test>, <Category: Third test>] - -If you call save() with invalid data, you'll get a ValueError. ->>> f = CategoryForm({'name': '', 'slug': 'not a slug!', 'url': 'foo'}) ->>> f.errors['name'] -[u'This field is required.'] ->>> f.errors['slug'] -[u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."] ->>> f.cleaned_data -Traceback (most recent call last): -... -AttributeError: 'CategoryForm' object has no attribute 'cleaned_data' ->>> f.save() -Traceback (most recent call last): -... -ValueError: The Category could not be created because the data didn't validate. ->>> f = CategoryForm({'name': '', 'slug': '', 'url': 'foo'}) ->>> f.save() -Traceback (most recent call last): -... -ValueError: The Category could not be created because the data didn't validate. - -Create a couple of Writers. ->>> w_royko = Writer(name='Mike Royko') ->>> w_royko.save() ->>> w_woodward = Writer(name='Bob Woodward') ->>> w_woodward.save() - -ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any -fields with the 'choices' attribute are represented by a ChoiceField. ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm(auto_id=False) ->>> print f -<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> -<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr> -<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> -<tr><th>Writer:</th><td><select name="writer"> -<option value="" selected="selected">---------</option> -<option value="...">Mike Royko</option> -<option value="...">Bob Woodward</option> -</select></td></tr> -<tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr> -<tr><th>Status:</th><td><select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></td></tr> -<tr><th>Categories:</th><td><select multiple="multiple" name="categories"> -<option value="1">Entertainment</option> -<option value="2">It's a test</option> -<option value="3">Third test</option> -</select><br /> Hold down "Control", or "Command" on a Mac, to select more than one.</td></tr> - -You can restrict a form to a subset of the complete list of fields -by providing a 'fields' argument. If you try to save a -model created with such a form, you need to ensure that the fields -that are _not_ on the form have default values, or are allowed to have -a value of None. If a field isn't specified on a form, the object created -from the form can't provide a value for that field! ->>> class PartialArticleForm(ModelForm): -... class Meta: -... model = Article -... fields = ('headline','pub_date') ->>> f = PartialArticleForm(auto_id=False) ->>> print f -<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr> -<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr> - -When the ModelForm is passed an instance, that instance's current values are -inserted as 'initial' data in each Field. ->>> w = Writer.objects.get(name='Mike Royko') ->>> class RoykoForm(ModelForm): -... class Meta: -... model = Writer ->>> f = RoykoForm(auto_id=False, instance=w) ->>> print f -<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr> - ->>> art = Article(headline='Test article', slug='test-article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.') ->>> art.save() ->>> art.id -1 ->>> class TestArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = TestArticleForm(auto_id=False, instance=art) ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" value="test-article" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> -<li>Writer: <select name="writer"> -<option value="">---------</option> -<option value="..." selected="selected">Mike Royko</option> -<option value="...">Bob Woodward</option> -</select></li> -<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> -<li>Status: <select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></li> -<li>Categories: <select multiple="multiple" name="categories"> -<option value="1">Entertainment</option> -<option value="2">It's a test</option> -<option value="3">Third test</option> -</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> ->>> f = TestArticleForm({'headline': u'Test headline', 'slug': 'test-headline', 'pub_date': u'1984-02-06', 'writer': unicode(w_royko.pk), 'article': 'Hello.'}, instance=art) ->>> f.errors -{} ->>> f.is_valid() -True ->>> test_art = f.save() ->>> test_art.id -1 ->>> test_art = Article.objects.get(id=1) ->>> test_art.headline -u'Test headline' - -You can create a form over a subset of the available fields -by specifying a 'fields' argument to form_for_instance. ->>> class PartialArticleForm(ModelForm): -... class Meta: -... model = Article -... fields=('headline', 'slug', 'pub_date') ->>> f = PartialArticleForm({'headline': u'New headline', 'slug': 'new-headline', 'pub_date': u'1988-01-04'}, auto_id=False, instance=art) ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> ->>> f.is_valid() -True ->>> new_art = f.save() ->>> new_art.id -1 ->>> new_art = Article.objects.get(id=1) ->>> new_art.headline -u'New headline' - -Add some categories and test the many-to-many form output. ->>> new_art.categories.all() -[] ->>> new_art.categories.add(Category.objects.get(name='Entertainment')) ->>> new_art.categories.all() -[<Category: Entertainment>] ->>> class TestArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = TestArticleForm(auto_id=False, instance=new_art) ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" value="new-headline" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li> -<li>Writer: <select name="writer"> -<option value="">---------</option> -<option value="..." selected="selected">Mike Royko</option> -<option value="...">Bob Woodward</option> -</select></li> -<li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li> -<li>Status: <select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></li> -<li>Categories: <select multiple="multiple" name="categories"> -<option value="1" selected="selected">Entertainment</option> -<option value="2">It's a test</option> -<option value="3">Third test</option> -</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> - -Initial values can be provided for model forms ->>> f = TestArticleForm(auto_id=False, initial={'headline': 'Your headline here', 'categories': ['1','2']}) ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" value="Your headline here" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" /></li> -<li>Writer: <select name="writer"> -<option value="" selected="selected">---------</option> -<option value="...">Mike Royko</option> -<option value="...">Bob Woodward</option> -</select></li> -<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li> -<li>Status: <select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></li> -<li>Categories: <select multiple="multiple" name="categories"> -<option value="1" selected="selected">Entertainment</option> -<option value="2" selected="selected">It's a test</option> -<option value="3">Third test</option> -</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> - ->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', -... 'writer': unicode(w_royko.pk), 'article': u'Hello.', 'categories': [u'1', u'2']}, instance=new_art) ->>> new_art = f.save() ->>> new_art.id -1 ->>> new_art = Article.objects.get(id=1) ->>> new_art.categories.order_by('name') -[<Category: Entertainment>, <Category: It's a test>] - -Now, submit form data with no categories. This deletes the existing categories. ->>> f = TestArticleForm({'headline': u'New headline', 'slug': u'new-headline', 'pub_date': u'1988-01-04', -... 'writer': unicode(w_royko.pk), 'article': u'Hello.'}, instance=new_art) ->>> new_art = f.save() ->>> new_art.id -1 ->>> new_art = Article.objects.get(id=1) ->>> new_art.categories.all() -[] - -Create a new article, with categories, via the form. ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', -... 'writer': unicode(w_royko.pk), 'article': u'Test.', 'categories': [u'1', u'2']}) ->>> new_art = f.save() ->>> new_art.id -2 ->>> new_art = Article.objects.get(id=2) ->>> new_art.categories.order_by('name') -[<Category: Entertainment>, <Category: It's a test>] - -Create a new article, with no categories, via the form. ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': u'walrus-was-paul', 'pub_date': u'1967-11-01', -... 'writer': unicode(w_royko.pk), 'article': u'Test.'}) ->>> new_art = f.save() ->>> new_art.id -3 ->>> new_art = Article.objects.get(id=3) ->>> new_art.categories.all() -[] - -Create a new article, with categories, via the form, but use commit=False. -The m2m data won't be saved until save_m2m() is invoked on the form. ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm({'headline': u'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': u'1967-11-01', -... 'writer': unicode(w_royko.pk), 'article': u'Test.', 'categories': [u'1', u'2']}) ->>> new_art = f.save(commit=False) - -# Manually save the instance ->>> new_art.save() ->>> new_art.id -4 - -# The instance doesn't have m2m data yet ->>> new_art = Article.objects.get(id=4) ->>> new_art.categories.all() -[] - -# Save the m2m data on the form ->>> f.save_m2m() ->>> new_art.categories.order_by('name') -[<Category: Entertainment>, <Category: It's a test>] - -Here, we define a custom ModelForm. Because it happens to have the same fields as -the Category model, we can just call the form's save() to apply its changes to an -existing Category instance. ->>> class ShortCategory(ModelForm): -... name = CharField(max_length=5) -... slug = CharField(max_length=5) -... url = CharField(max_length=3) ->>> cat = Category.objects.get(name='Third test') ->>> cat -<Category: Third test> ->>> cat.id -3 ->>> form = ShortCategory({'name': 'Third', 'slug': 'third', 'url': '3rd'}, instance=cat) ->>> form.save() -<Category: Third> ->>> Category.objects.get(id=3) -<Category: Third> - -Here, we demonstrate that choices for a ForeignKey ChoiceField are determined -at runtime, based on the data in the database when the form is displayed, not -the data in the database when the form is instantiated. ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm(auto_id=False) ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" /></li> -<li>Writer: <select name="writer"> -<option value="" selected="selected">---------</option> -<option value="...">Mike Royko</option> -<option value="...">Bob Woodward</option> -</select></li> -<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li> -<li>Status: <select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></li> -<li>Categories: <select multiple="multiple" name="categories"> -<option value="1">Entertainment</option> -<option value="2">It's a test</option> -<option value="3">Third</option> -</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> ->>> Category.objects.create(name='Fourth', url='4th') -<Category: Fourth> ->>> Writer.objects.create(name='Carl Bernstein') -<Writer: Carl Bernstein> ->>> print f.as_ul() -<li>Headline: <input type="text" name="headline" maxlength="50" /></li> -<li>Slug: <input type="text" name="slug" maxlength="50" /></li> -<li>Pub date: <input type="text" name="pub_date" /></li> -<li>Writer: <select name="writer"> -<option value="" selected="selected">---------</option> -<option value="...">Mike Royko</option> -<option value="...">Bob Woodward</option> -<option value="...">Carl Bernstein</option> -</select></li> -<li>Article: <textarea rows="10" cols="40" name="article"></textarea></li> -<li>Status: <select name="status"> -<option value="" selected="selected">---------</option> -<option value="1">Draft</option> -<option value="2">Pending</option> -<option value="3">Live</option> -</select></li> -<li>Categories: <select multiple="multiple" name="categories"> -<option value="1">Entertainment</option> -<option value="2">It's a test</option> -<option value="3">Third</option> -<option value="4">Fourth</option> -</select> Hold down "Control", or "Command" on a Mac, to select more than one.</li> - -# ModelChoiceField ############################################################ - ->>> from django.forms import ModelChoiceField, ModelMultipleChoiceField - ->>> f = ModelChoiceField(Category.objects.all()) ->>> list(f.choices) -[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')] ->>> f.clean('') -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean(0) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] ->>> f.clean(3) -<Category: Third> ->>> f.clean(2) -<Category: It's a test> - -# Add a Category object *after* the ModelChoiceField has already been -# instantiated. This proves clean() checks the database during clean() rather -# than caching it at time of instantiation. ->>> Category.objects.create(name='Fifth', url='5th') -<Category: Fifth> ->>> f.clean(5) -<Category: Fifth> - -# Delete a Category object *after* the ModelChoiceField has already been -# instantiated. This proves clean() checks the database during clean() rather -# than caching it at time of instantiation. ->>> Category.objects.get(url='5th').delete() ->>> f.clean(5) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - ->>> f = ModelChoiceField(Category.objects.filter(pk=1), required=False) ->>> print f.clean('') -None ->>> f.clean('') ->>> f.clean('1') -<Category: Entertainment> ->>> f.clean('100') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - -# queryset can be changed after the field is created. ->>> f.queryset = Category.objects.exclude(name='Fourth') ->>> list(f.choices) -[(u'', u'---------'), (1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')] ->>> f.clean(3) -<Category: Third> ->>> f.clean(4) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] - -# check that we can safely iterate choices repeatedly ->>> gen_one = list(f.choices) ->>> gen_two = f.choices ->>> gen_one[2] -(2L, u"It's a test") ->>> list(gen_two) -[(u'', u'---------'), (1L, u'Entertainment'), (2L, u"It's a test"), (3L, u'Third')] - -# check that we can override the label_from_instance method to print custom labels (#4620) ->>> f.queryset = Category.objects.all() ->>> f.label_from_instance = lambda obj: "category " + str(obj) ->>> list(f.choices) -[(u'', u'---------'), (1L, 'category Entertainment'), (2L, "category It's a test"), (3L, 'category Third'), (4L, 'category Fourth')] - -# ModelMultipleChoiceField #################################################### - ->>> f = ModelMultipleChoiceField(Category.objects.all()) ->>> list(f.choices) -[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third'), (4, u'Fourth')] ->>> f.clean(None) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean([]) -Traceback (most recent call last): -... -ValidationError: [u'This field is required.'] ->>> f.clean([1]) -[<Category: Entertainment>] ->>> f.clean([2]) -[<Category: It's a test>] ->>> f.clean(['1']) -[<Category: Entertainment>] ->>> f.clean(['1', '2']) -[<Category: Entertainment>, <Category: It's a test>] ->>> f.clean([1, '2']) -[<Category: Entertainment>, <Category: It's a test>] ->>> f.clean((1, '2')) -[<Category: Entertainment>, <Category: It's a test>] ->>> f.clean(['100']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 100 is not one of the available choices.'] ->>> f.clean('hello') -Traceback (most recent call last): -... -ValidationError: [u'Enter a list of values.'] ->>> f.clean(['fail']) -Traceback (most recent call last): -... -ValidationError: [u'"fail" is not a valid value for a primary key.'] - -# Add a Category object *after* the ModelMultipleChoiceField has already been -# instantiated. This proves clean() checks the database during clean() rather -# than caching it at time of instantiation. ->>> Category.objects.create(id=6, name='Sixth', url='6th') -<Category: Sixth> ->>> f.clean([6]) -[<Category: Sixth>] - -# Delete a Category object *after* the ModelMultipleChoiceField has already been -# instantiated. This proves clean() checks the database during clean() rather -# than caching it at time of instantiation. ->>> Category.objects.get(url='6th').delete() ->>> f.clean([6]) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 6 is not one of the available choices.'] - ->>> f = ModelMultipleChoiceField(Category.objects.all(), required=False) ->>> f.clean([]) -[] ->>> f.clean(()) -[] ->>> f.clean(['10']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 10 is not one of the available choices.'] ->>> f.clean(['3', '10']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 10 is not one of the available choices.'] ->>> f.clean(['1', '10']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 10 is not one of the available choices.'] - -# queryset can be changed after the field is created. ->>> f.queryset = Category.objects.exclude(name='Fourth') ->>> list(f.choices) -[(1, u'Entertainment'), (2, u"It's a test"), (3, u'Third')] ->>> f.clean([3]) -[<Category: Third>] ->>> f.clean([4]) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 4 is not one of the available choices.'] ->>> f.clean(['3', '4']) -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 4 is not one of the available choices.'] - ->>> f.queryset = Category.objects.all() ->>> f.label_from_instance = lambda obj: "multicategory " + str(obj) ->>> list(f.choices) -[(1L, 'multicategory Entertainment'), (2L, "multicategory It's a test"), (3L, 'multicategory Third'), (4L, 'multicategory Fourth')] - -# OneToOneField ############################################################### - ->>> class ImprovedArticleForm(ModelForm): -... class Meta: -... model = ImprovedArticle ->>> ImprovedArticleForm.base_fields.keys() -['article'] - ->>> class ImprovedArticleWithParentLinkForm(ModelForm): -... class Meta: -... model = ImprovedArticleWithParentLink ->>> ImprovedArticleWithParentLinkForm.base_fields.keys() -[] - ->>> bw = BetterWriter(name=u'Joe Better', score=10) ->>> bw.save() ->>> sorted(model_to_dict(bw).keys()) -['id', 'name', 'score', 'writer_ptr'] - ->>> class BetterWriterForm(ModelForm): -... class Meta: -... model = BetterWriter ->>> form = BetterWriterForm({'name': 'Some Name', 'score': 12}) ->>> form.is_valid() -True ->>> bw2 = form.save() ->>> bw2.delete() - - ->>> class WriterProfileForm(ModelForm): -... class Meta: -... model = WriterProfile ->>> form = WriterProfileForm() ->>> print form.as_p() -<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer"> -<option value="" selected="selected">---------</option> -<option value="...">Mike Royko</option> -<option value="...">Bob Woodward</option> -<option value="...">Carl Bernstein</option> -<option value="...">Joe Better</option> -</select></p> -<p><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" /></p> - ->>> data = { -... 'writer': unicode(w_woodward.pk), -... 'age': u'65', -... } ->>> form = WriterProfileForm(data) ->>> instance = form.save() ->>> instance -<WriterProfile: Bob Woodward is 65> - ->>> form = WriterProfileForm(instance=instance) ->>> print form.as_p() -<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer"> -<option value="">---------</option> -<option value="...">Mike Royko</option> -<option value="..." selected="selected">Bob Woodward</option> -<option value="...">Carl Bernstein</option> -<option value="...">Joe Better</option> -</select></p> -<p><label for="id_age">Age:</label> <input type="text" name="age" value="65" id="id_age" /></p> - -# PhoneNumberField ############################################################ - ->>> class PhoneNumberForm(ModelForm): -... class Meta: -... model = PhoneNumber ->>> f = PhoneNumberForm({'phone': '(312) 555-1212', 'description': 'Assistance'}) ->>> f.is_valid() -True ->>> f.cleaned_data['phone'] -u'312-555-1212' ->>> f.cleaned_data['description'] -u'Assistance' - -# FileField ################################################################### - -# File forms. - ->>> class TextFileForm(ModelForm): -... class Meta: -... model = TextFile - -# Test conditions when files is either not given or empty. - ->>> f = TextFileForm(data={'description': u'Assistance'}) ->>> f.is_valid() -False ->>> f = TextFileForm(data={'description': u'Assistance'}, files={}) ->>> f.is_valid() -False - -# Upload a file and ensure it all works as expected. - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')}) ->>> f.is_valid() -True ->>> type(f.cleaned_data['file']) -<class 'django.core.files.uploadedfile.SimpleUploadedFile'> ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test1.txt> - ->>> instance.file.delete() - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')}) ->>> f.is_valid() -True ->>> type(f.cleaned_data['file']) -<class 'django.core.files.uploadedfile.SimpleUploadedFile'> ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test1.txt> - -# Check if the max_length attribute has been inherited from the model. ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test-maxlength.txt', 'hello world')}) ->>> f.is_valid() -False - -# Edit an instance that already has the file defined in the model. This will not -# save the file again, but leave it exactly as it is. - ->>> f = TextFileForm(data={'description': u'Assistance'}, instance=instance) ->>> f.is_valid() -True ->>> f.cleaned_data['file'] -<FieldFile: tests/test1.txt> ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test1.txt> - -# Delete the current file since this is not done by Django. ->>> instance.file.delete() - -# Override the file by uploading a new one. - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}, instance=instance) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test2.txt> - -# Delete the current file since this is not done by Django. ->>> instance.file.delete() - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test2.txt> - -# Delete the current file since this is not done by Django. ->>> instance.file.delete() - ->>> instance.delete() - -# Test the non-required FileField ->>> f = TextFileForm(data={'description': u'Assistance'}) ->>> f.fields['file'].required = False ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.file -<FieldFile: None> - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test3.txt> - -# Instance can be edited w/out re-uploading the file and existing file should be preserved. - ->>> f = TextFileForm(data={'description': u'New Description'}, instance=instance) ->>> f.fields['file'].required = False ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.description -u'New Description' ->>> instance.file -<FieldFile: tests/test3.txt> - -# Delete the current file since this is not done by Django. ->>> instance.file.delete() ->>> instance.delete() - ->>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.file -<FieldFile: tests/test3.txt> - -# Delete the current file since this is not done by Django. ->>> instance.file.delete() ->>> instance.delete() - -# BigIntegerField ################################################################ ->>> class BigIntForm(forms.ModelForm): -... class Meta: -... model = BigInt -... ->>> bif = BigIntForm({'biggie': '-9223372036854775808'}) ->>> bif.is_valid() -True ->>> bif = BigIntForm({'biggie': '-9223372036854775809'}) ->>> bif.is_valid() -False ->>> bif.errors -{'biggie': [u'Ensure this value is greater than or equal to -9223372036854775808.']} ->>> bif = BigIntForm({'biggie': '9223372036854775807'}) ->>> bif.is_valid() -True ->>> bif = BigIntForm({'biggie': '9223372036854775808'}) ->>> bif.is_valid() -False ->>> bif.errors -{'biggie': [u'Ensure this value is less than or equal to 9223372036854775807.']} -"""} - -if test_images: - __test__['API_TESTS'] += """ -# ImageField ################################################################### - -# ImageField and FileField are nearly identical, but they differ slighty when -# it comes to validation. This specifically tests that #6302 is fixed for -# both file fields and image fields. - ->>> class ImageFileForm(ModelForm): -... class Meta: -... model = ImageFile - ->>> image_data = open(os.path.join(os.path.dirname(__file__), "test.png"), 'rb').read() ->>> image_data2 = open(os.path.join(os.path.dirname(__file__), "test2.png"), 'rb').read() - ->>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)}) ->>> f.is_valid() -True ->>> type(f.cleaned_data['image']) -<class 'django.core.files.uploadedfile.SimpleUploadedFile'> ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test.png> ->>> instance.width -16 ->>> instance.height -16 - -# Delete the current file since this is not done by Django, but don't save -# because the dimension fields are not null=True. ->>> instance.image.delete(save=False) - ->>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)}) ->>> f.is_valid() -True ->>> type(f.cleaned_data['image']) -<class 'django.core.files.uploadedfile.SimpleUploadedFile'> ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test.png> ->>> instance.width -16 ->>> instance.height -16 - -# Edit an instance that already has the (required) image defined in the model. This will not -# save the image again, but leave it exactly as it is. - ->>> f = ImageFileForm(data={'description': u'Look, it changed'}, instance=instance) ->>> f.is_valid() -True ->>> f.cleaned_data['image'] -<...FieldFile: tests/test.png> ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test.png> ->>> instance.height -16 ->>> instance.width -16 - -# Delete the current file since this is not done by Django, but don't save -# because the dimension fields are not null=True. ->>> instance.image.delete(save=False) - -# Override the file by uploading a new one. - ->>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': SimpleUploadedFile('test2.png', image_data2)}, instance=instance) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test2.png> ->>> instance.height -32 ->>> instance.width -48 - -# Delete the current file since this is not done by Django, but don't save -# because the dimension fields are not null=True. ->>> instance.image.delete(save=False) ->>> instance.delete() - ->>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': SimpleUploadedFile('test2.png', image_data2)}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test2.png> ->>> instance.height -32 ->>> instance.width -48 - -# Delete the current file since this is not done by Django, but don't save -# because the dimension fields are not null=True. ->>> instance.image.delete(save=False) ->>> instance.delete() - -# Test the non-required ImageField - ->>> class OptionalImageFileForm(ModelForm): -... class Meta: -... model = OptionalImageFile - ->>> f = OptionalImageFileForm(data={'description': u'Test'}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: None> ->>> instance.width ->>> instance.height - ->>> f = OptionalImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}, instance=instance) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test3.png> ->>> instance.width -16 ->>> instance.height -16 - -# Editing the instance without re-uploading the image should not affect the image or its width/height properties ->>> f = OptionalImageFileForm(data={'description': u'New Description'}, instance=instance) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.description -u'New Description' ->>> instance.image -<...FieldFile: tests/test3.png> ->>> instance.width -16 ->>> instance.height -16 - -# Delete the current file since this is not done by Django. ->>> instance.image.delete() ->>> instance.delete() - ->>> f = OptionalImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test4.png', image_data2)}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: tests/test4.png> ->>> instance.width -48 ->>> instance.height -32 ->>> instance.delete() - -# Test callable upload_to behavior that's dependent on the value of another field in the model ->>> f = ImageFileForm(data={'description': u'And a final one', 'path': 'foo'}, files={'image': SimpleUploadedFile('test4.png', image_data)}) ->>> f.is_valid() -True ->>> instance = f.save() ->>> instance.image -<...FieldFile: foo/test4.png> ->>> instance.delete() -""" - -__test__['API_TESTS'] += """ - -# Media on a ModelForm ######################################################## - -# Similar to a regular Form class you can define custom media to be used on -# the ModelForm. - ->>> class ModelFormWithMedia(ModelForm): -... class Media: -... js = ('/some/form/javascript',) -... css = { -... 'all': ('/some/form/css',) -... } -... class Meta: -... model = PhoneNumber ->>> f = ModelFormWithMedia() ->>> print f.media -<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" /> -<script type="text/javascript" src="/some/form/javascript"></script> - ->>> class CommaSeparatedIntegerForm(ModelForm): -... class Meta: -... model = CommaSeparatedInteger - ->>> f = CommaSeparatedIntegerForm({'field': '1,2,3'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'field': u'1,2,3'} ->>> f = CommaSeparatedIntegerForm({'field': '1a,2'}) ->>> f.errors -{'field': [u'Enter only digits separated by commas.']} ->>> f = CommaSeparatedIntegerForm({'field': ',,,,'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'field': u',,,,'} ->>> f = CommaSeparatedIntegerForm({'field': '1.2'}) ->>> f.errors -{'field': [u'Enter only digits separated by commas.']} ->>> f = CommaSeparatedIntegerForm({'field': '1,a,2'}) ->>> f.errors -{'field': [u'Enter only digits separated by commas.']} ->>> f = CommaSeparatedIntegerForm({'field': '1,,2'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'field': u'1,,2'} ->>> f = CommaSeparatedIntegerForm({'field': '1'}) ->>> f.is_valid() -True ->>> f.cleaned_data -{'field': u'1'} - -This Price instance generated by this form is not valid because the quantity -field is required, but the form is valid because the field is excluded from -the form. This is for backwards compatibility. - ->>> class PriceForm(ModelForm): -... class Meta: -... model = Price -... exclude = ('quantity',) ->>> form = PriceForm({'price': '6.00'}) ->>> form.is_valid() -True ->>> price = form.save(commit=False) ->>> price.full_clean() -Traceback (most recent call last): - ... -ValidationError: {'quantity': [u'This field cannot be null.']} - -The form should not validate fields that it doesn't contain even if they are -specified using 'fields', not 'exclude'. -... class Meta: -... model = Price -... fields = ('price',) ->>> form = PriceForm({'price': '6.00'}) ->>> form.is_valid() -True - -The form should still have an instance of a model that is not complete and -not saved into a DB yet. - ->>> form.instance.price -Decimal('6.00') ->>> form.instance.quantity is None -True ->>> form.instance.pk is None -True - -# Choices on CharField and IntegerField ->>> class ArticleForm(ModelForm): -... class Meta: -... model = Article ->>> f = ArticleForm() ->>> f.fields['status'].clean('42') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. 42 is not one of the available choices.'] - ->>> class ArticleStatusForm(ModelForm): -... class Meta: -... model = ArticleStatus ->>> f = ArticleStatusForm() ->>> f.fields['status'].clean('z') -Traceback (most recent call last): -... -ValidationError: [u'Select a valid choice. z is not one of the available choices.'] - -# Foreign keys which use to_field ############################################# - ->>> apple = Inventory.objects.create(barcode=86, name='Apple') ->>> pear = Inventory.objects.create(barcode=22, name='Pear') ->>> core = Inventory.objects.create(barcode=87, name='Core', parent=apple) - ->>> field = ModelChoiceField(Inventory.objects.all(), to_field_name='barcode') ->>> for choice in field.choices: -... print choice -(u'', u'---------') -(86, u'Apple') -(22, u'Pear') -(87, u'Core') - ->>> class InventoryForm(ModelForm): -... class Meta: -... model = Inventory ->>> form = InventoryForm(instance=core) ->>> print form['parent'] -<select name="parent" id="id_parent"> -<option value="">---------</option> -<option value="86" selected="selected">Apple</option> -<option value="22">Pear</option> -<option value="87">Core</option> -</select> - ->>> data = model_to_dict(core) ->>> data['parent'] = '22' ->>> form = InventoryForm(data=data, instance=core) ->>> core = form.save() ->>> core.parent -<Inventory: Pear> - ->>> class CategoryForm(ModelForm): -... description = forms.CharField() -... class Meta: -... model = Category -... fields = ['description', 'url'] - ->>> CategoryForm.base_fields.keys() -['description', 'url'] - ->>> print CategoryForm() -<tr><th><label for="id_description">Description:</label></th><td><input type="text" name="description" id="id_description" /></td></tr> -<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr> - -# Model field that returns None to exclude itself with explicit fields ######## - ->>> class CustomFieldForExclusionForm(ModelForm): -... class Meta: -... model = CustomFieldForExclusionModel -... fields = ['name', 'markup'] - ->>> CustomFieldForExclusionForm.base_fields.keys() -['name'] - ->>> print CustomFieldForExclusionForm() -<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="10" /></td></tr> - -# Clean up ->>> import shutil ->>> shutil.rmtree(temp_storage_dir) -""" diff --git a/parts/django/tests/modeltests/model_forms/test.png b/parts/django/tests/modeltests/model_forms/test.png Binary files differdeleted file mode 100644 index 4f17cd0..0000000 --- a/parts/django/tests/modeltests/model_forms/test.png +++ /dev/null diff --git a/parts/django/tests/modeltests/model_forms/test2.png b/parts/django/tests/modeltests/model_forms/test2.png Binary files differdeleted file mode 100644 index 10702f7..0000000 --- a/parts/django/tests/modeltests/model_forms/test2.png +++ /dev/null diff --git a/parts/django/tests/modeltests/model_forms/tests.py b/parts/django/tests/modeltests/model_forms/tests.py deleted file mode 100644 index c5647c7..0000000 --- a/parts/django/tests/modeltests/model_forms/tests.py +++ /dev/null @@ -1,185 +0,0 @@ -import datetime -from django.test import TestCase -from django import forms -from models import Category, Writer, Book, DerivedBook, Post -from mforms import (ProductForm, PriceForm, BookForm, DerivedBookForm, - ExplicitPKForm, PostForm, DerivedPostForm, CustomWriterForm) - - -class IncompleteCategoryFormWithFields(forms.ModelForm): - """ - A form that replaces the model's url field with a custom one. This should - prevent the model field's validation from being called. - """ - url = forms.CharField(required=False) - - class Meta: - fields = ('name', 'slug') - model = Category - -class IncompleteCategoryFormWithExclude(forms.ModelForm): - """ - A form that replaces the model's url field with a custom one. This should - prevent the model field's validation from being called. - """ - url = forms.CharField(required=False) - - class Meta: - exclude = ['url'] - model = Category - - -class ValidationTest(TestCase): - def test_validates_with_replaced_field_not_specified(self): - form = IncompleteCategoryFormWithFields(data={'name': 'some name', 'slug': 'some-slug'}) - assert form.is_valid() - - def test_validates_with_replaced_field_excluded(self): - form = IncompleteCategoryFormWithExclude(data={'name': 'some name', 'slug': 'some-slug'}) - assert form.is_valid() - - def test_notrequired_overrides_notblank(self): - form = CustomWriterForm({}) - assert form.is_valid() - -# unique/unique_together validation -class UniqueTest(TestCase): - def setUp(self): - self.writer = Writer.objects.create(name='Mike Royko') - - def test_simple_unique(self): - form = ProductForm({'slug': 'teddy-bear-blue'}) - self.assertTrue(form.is_valid()) - obj = form.save() - form = ProductForm({'slug': 'teddy-bear-blue'}) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['slug'], [u'Product with this Slug already exists.']) - form = ProductForm({'slug': 'teddy-bear-blue'}, instance=obj) - self.assertTrue(form.is_valid()) - - def test_unique_together(self): - """ModelForm test of unique_together constraint""" - form = PriceForm({'price': '6.00', 'quantity': '1'}) - self.assertTrue(form.is_valid()) - form.save() - form = PriceForm({'price': '6.00', 'quantity': '1'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['__all__'], [u'Price with this Price and Quantity already exists.']) - - def test_unique_null(self): - title = 'I May Be Wrong But I Doubt It' - form = BookForm({'title': title, 'author': self.writer.pk}) - self.assertTrue(form.is_valid()) - form.save() - form = BookForm({'title': title, 'author': self.writer.pk}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['__all__'], [u'Book with this Title and Author already exists.']) - form = BookForm({'title': title}) - self.assertTrue(form.is_valid()) - form.save() - form = BookForm({'title': title}) - self.assertTrue(form.is_valid()) - - def test_inherited_unique(self): - title = 'Boss' - Book.objects.create(title=title, author=self.writer, special_id=1) - form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'special_id': u'1', 'isbn': '12345'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['special_id'], [u'Book with this Special id already exists.']) - - def test_inherited_unique_together(self): - title = 'Boss' - form = BookForm({'title': title, 'author': self.writer.pk}) - self.assertTrue(form.is_valid()) - form.save() - form = DerivedBookForm({'title': title, 'author': self.writer.pk, 'isbn': '12345'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['__all__'], [u'Book with this Title and Author already exists.']) - - def test_abstract_inherited_unique(self): - title = 'Boss' - isbn = '12345' - dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn) - form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'isbn': isbn}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['isbn'], [u'Derived book with this Isbn already exists.']) - - def test_abstract_inherited_unique_together(self): - title = 'Boss' - isbn = '12345' - dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn) - form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'isbn': '9876', 'suffix1': u'0', 'suffix2': u'0'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['__all__'], [u'Derived book with this Suffix1 and Suffix2 already exists.']) - - def test_explicitpk_unspecified(self): - """Test for primary_key being in the form and failing validation.""" - form = ExplicitPKForm({'key': u'', 'desc': u'' }) - self.assertFalse(form.is_valid()) - - def test_explicitpk_unique(self): - """Ensure keys and blank character strings are tested for uniqueness.""" - form = ExplicitPKForm({'key': u'key1', 'desc': u''}) - self.assertTrue(form.is_valid()) - form.save() - form = ExplicitPKForm({'key': u'key1', 'desc': u''}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 3) - self.assertEqual(form.errors['__all__'], [u'Explicit pk with this Key and Desc already exists.']) - self.assertEqual(form.errors['desc'], [u'Explicit pk with this Desc already exists.']) - self.assertEqual(form.errors['key'], [u'Explicit pk with this Key already exists.']) - - def test_unique_for_date(self): - p = Post.objects.create(title="Django 1.0 is released", - slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3)) - form = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['title'], [u'Title must be unique for Posted date.']) - form = PostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'}) - self.assertTrue(form.is_valid()) - form = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'}) - self.assertTrue(form.is_valid()) - form = PostForm({'slug': "Django 1.0", 'posted': '2008-01-01'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['slug'], [u'Slug must be unique for Posted year.']) - form = PostForm({'subtitle': "Finally", 'posted': '2008-09-30'}) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['subtitle'], [u'Subtitle must be unique for Posted month.']) - form = PostForm({'subtitle': "Finally", "title": "Django 1.0 is released", - "slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p) - self.assertTrue(form.is_valid()) - form = PostForm({'title': "Django 1.0 is released"}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['posted'], [u'This field is required.']) - - def test_inherited_unique_for_date(self): - p = Post.objects.create(title="Django 1.0 is released", - slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3)) - form = DerivedPostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['title'], [u'Title must be unique for Posted date.']) - form = DerivedPostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'}) - self.assertTrue(form.is_valid()) - form = DerivedPostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'}) - self.assertTrue(form.is_valid()) - form = DerivedPostForm({'slug': "Django 1.0", 'posted': '2008-01-01'}) - self.assertFalse(form.is_valid()) - self.assertEqual(len(form.errors), 1) - self.assertEqual(form.errors['slug'], [u'Slug must be unique for Posted year.']) - form = DerivedPostForm({'subtitle': "Finally", 'posted': '2008-09-30'}) - self.assertFalse(form.is_valid()) - self.assertEqual(form.errors['subtitle'], [u'Subtitle must be unique for Posted month.']) - form = DerivedPostForm({'subtitle': "Finally", "title": "Django 1.0 is released", - "slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p) - self.assertTrue(form.is_valid()) - diff --git a/parts/django/tests/modeltests/model_formsets/__init__.py b/parts/django/tests/modeltests/model_formsets/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/model_formsets/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/model_formsets/models.py b/parts/django/tests/modeltests/model_formsets/models.py deleted file mode 100644 index 3eca696..0000000 --- a/parts/django/tests/modeltests/model_formsets/models.py +++ /dev/null @@ -1,193 +0,0 @@ -import datetime -from django.db import models - -class Author(models.Model): - name = models.CharField(max_length=100) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - -class BetterAuthor(Author): - write_speed = models.IntegerField() - -class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - - class Meta: - unique_together = ( - ('author', 'title'), - ) - ordering = ['id'] - - def __unicode__(self): - return self.title - -class BookWithCustomPK(models.Model): - my_pk = models.DecimalField(max_digits=5, decimal_places=0, primary_key=True) - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - - def __unicode__(self): - return u'%s: %s' % (self.my_pk, self.title) - -class Editor(models.Model): - name = models.CharField(max_length=100) - -class BookWithOptionalAltEditor(models.Model): - author = models.ForeignKey(Author) - # Optional secondary author - alt_editor = models.ForeignKey(Editor, blank=True, null=True) - title = models.CharField(max_length=100) - - class Meta: - unique_together = ( - ('author', 'title', 'alt_editor'), - ) - - def __unicode__(self): - return self.title - -class AlternateBook(Book): - notes = models.CharField(max_length=100) - - def __unicode__(self): - return u'%s - %s' % (self.title, self.notes) - -class AuthorMeeting(models.Model): - name = models.CharField(max_length=100) - authors = models.ManyToManyField(Author) - created = models.DateField(editable=False) - - def __unicode__(self): - return self.name - -class CustomPrimaryKey(models.Model): - my_pk = models.CharField(max_length=10, primary_key=True) - some_field = models.CharField(max_length=100) - - -# models for inheritance tests. - -class Place(models.Model): - name = models.CharField(max_length=50) - city = models.CharField(max_length=50) - - def __unicode__(self): - return self.name - -class Owner(models.Model): - auto_id = models.AutoField(primary_key=True) - name = models.CharField(max_length=100) - place = models.ForeignKey(Place) - - def __unicode__(self): - return "%s at %s" % (self.name, self.place) - -class Location(models.Model): - place = models.ForeignKey(Place, unique=True) - # this is purely for testing the data doesn't matter here :) - lat = models.CharField(max_length=100) - lon = models.CharField(max_length=100) - -class OwnerProfile(models.Model): - owner = models.OneToOneField(Owner, primary_key=True) - age = models.PositiveIntegerField() - - def __unicode__(self): - return "%s is %d" % (self.owner.name, self.age) - -class Restaurant(Place): - serves_pizza = models.BooleanField() - - def __unicode__(self): - return self.name - -class Product(models.Model): - slug = models.SlugField(unique=True) - - def __unicode__(self): - return self.slug - -class Price(models.Model): - price = models.DecimalField(max_digits=10, decimal_places=2) - quantity = models.PositiveIntegerField() - - def __unicode__(self): - return u"%s for %s" % (self.quantity, self.price) - - class Meta: - unique_together = (('price', 'quantity'),) - -class MexicanRestaurant(Restaurant): - serves_tacos = models.BooleanField() - -class ClassyMexicanRestaurant(MexicanRestaurant): - restaurant = models.OneToOneField(MexicanRestaurant, parent_link=True, primary_key=True) - tacos_are_yummy = models.BooleanField() - -# models for testing unique_together validation when a fk is involved and -# using inlineformset_factory. -class Repository(models.Model): - name = models.CharField(max_length=25) - - def __unicode__(self): - return self.name - -class Revision(models.Model): - repository = models.ForeignKey(Repository) - revision = models.CharField(max_length=40) - - class Meta: - unique_together = (("repository", "revision"),) - - def __unicode__(self): - return u"%s (%s)" % (self.revision, unicode(self.repository)) - -# models for testing callable defaults (see bug #7975). If you define a model -# with a callable default value, you cannot rely on the initial value in a -# form. -class Person(models.Model): - name = models.CharField(max_length=128) - -class Membership(models.Model): - person = models.ForeignKey(Person) - date_joined = models.DateTimeField(default=datetime.datetime.now) - karma = models.IntegerField() - -# models for testing a null=True fk to a parent -class Team(models.Model): - name = models.CharField(max_length=100) - -class Player(models.Model): - team = models.ForeignKey(Team, null=True) - name = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - -# Models for testing custom ModelForm save methods in formsets and inline formsets -class Poet(models.Model): - name = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - -class Poem(models.Model): - poet = models.ForeignKey(Poet) - name = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - -class Post(models.Model): - title = models.CharField(max_length=50, unique_for_date='posted', blank=True) - slug = models.CharField(max_length=50, unique_for_year='posted', blank=True) - subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True) - posted = models.DateField() - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/model_formsets/tests.py b/parts/django/tests/modeltests/model_formsets/tests.py deleted file mode 100644 index c856a5f..0000000 --- a/parts/django/tests/modeltests/model_formsets/tests.py +++ /dev/null @@ -1,1159 +0,0 @@ -import datetime -import re -from datetime import date -from decimal import Decimal - -from django import forms -from django.db import models -from django.forms.models import (_get_foreign_key, inlineformset_factory, - modelformset_factory, modelformset_factory) -from django.test import TestCase - -from modeltests.model_formsets.models import ( - Author, BetterAuthor, Book, BookWithCustomPK, Editor, - BookWithOptionalAltEditor, AlternateBook, AuthorMeeting, CustomPrimaryKey, - Place, Owner, Location, OwnerProfile, Restaurant, Product, Price, - MexicanRestaurant, ClassyMexicanRestaurant, Repository, Revision, - Person, Membership, Team, Player, Poet, Poem, Post) - -class DeletionTests(TestCase): - def test_deletion(self): - PoetFormSet = modelformset_factory(Poet, can_delete=True) - poet = Poet.objects.create(name='test') - data = { - 'form-TOTAL_FORMS': u'1', - 'form-INITIAL_FORMS': u'1', - 'form-MAX_NUM_FORMS': u'0', - 'form-0-id': str(poet.pk), - 'form-0-name': u'test', - 'form-0-DELETE': u'on', - } - formset = PoetFormSet(data, queryset=Poet.objects.all()) - formset.save() - self.assertTrue(formset.is_valid()) - self.assertEqual(Poet.objects.count(), 0) - - def test_add_form_deletion_when_invalid(self): - """ - Make sure that an add form that is filled out, but marked for deletion - doesn't cause validation errors. - """ - PoetFormSet = modelformset_factory(Poet, can_delete=True) - data = { - 'form-TOTAL_FORMS': u'1', - 'form-INITIAL_FORMS': u'0', - 'form-MAX_NUM_FORMS': u'0', - 'form-0-id': u'', - 'form-0-name': u'x' * 1000, - } - formset = PoetFormSet(data, queryset=Poet.objects.all()) - # Make sure this form doesn't pass validation. - self.assertEqual(formset.is_valid(), False) - self.assertEqual(Poet.objects.count(), 0) - - # Then make sure that it *does* pass validation and delete the object, - # even though the data isn't actually valid. - data['form-0-DELETE'] = 'on' - formset = PoetFormSet(data, queryset=Poet.objects.all()) - self.assertEqual(formset.is_valid(), True) - formset.save() - self.assertEqual(Poet.objects.count(), 0) - - def test_change_form_deletion_when_invalid(self): - """ - Make sure that an add form that is filled out, but marked for deletion - doesn't cause validation errors. - """ - PoetFormSet = modelformset_factory(Poet, can_delete=True) - poet = Poet.objects.create(name='test') - data = { - 'form-TOTAL_FORMS': u'1', - 'form-INITIAL_FORMS': u'1', - 'form-MAX_NUM_FORMS': u'0', - 'form-0-id': u'1', - 'form-0-name': u'x' * 1000, - } - formset = PoetFormSet(data, queryset=Poet.objects.all()) - # Make sure this form doesn't pass validation. - self.assertEqual(formset.is_valid(), False) - self.assertEqual(Poet.objects.count(), 1) - - # Then make sure that it *does* pass validation and delete the object, - # even though the data isn't actually valid. - data['form-0-DELETE'] = 'on' - formset = PoetFormSet(data, queryset=Poet.objects.all()) - self.assertEqual(formset.is_valid(), True) - formset.save() - self.assertEqual(Poet.objects.count(), 0) - -class ModelFormsetTest(TestCase): - def test_simple_save(self): - qs = Author.objects.all() - AuthorFormSet = modelformset_factory(Author, extra=3) - - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_form-1-name">Name:</label> <input id="id_form-1-name" type="text" name="form-1-name" maxlength="100" /><input type="hidden" name="form-1-id" id="id_form-1-id" /></p>') - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_form-2-name">Name:</label> <input id="id_form-2-name" type="text" name="form-2-name" maxlength="100" /><input type="hidden" name="form-2-id" id="id_form-2-id" /></p>') - - data = { - 'form-TOTAL_FORMS': '3', # the number of forms rendered - 'form-INITIAL_FORMS': '0', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-name': 'Charles Baudelaire', - 'form-1-name': 'Arthur Rimbaud', - 'form-2-name': '', - } - - formset = AuthorFormSet(data=data, queryset=qs) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 2) - author1, author2 = saved - self.assertEqual(author1, Author.objects.get(name='Charles Baudelaire')) - self.assertEqual(author2, Author.objects.get(name='Arthur Rimbaud')) - - authors = list(Author.objects.order_by('name')) - self.assertEqual(authors, [author2, author1]) - - # Gah! We forgot Paul Verlaine. Let's create a formset to edit the - # existing authors with an extra form to add him. We *could* pass in a - # queryset to restrict the Author objects we edit, but in this case - # we'll use it to display them in alphabetical order by name. - - qs = Author.objects.order_by('name') - AuthorFormSet = modelformset_factory(Author, extra=1, can_delete=False) - - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" value="Arthur Rimbaud" maxlength="100" /><input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /></p>' % author2.id) - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_form-1-name">Name:</label> <input id="id_form-1-name" type="text" name="form-1-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" /></p>' % author1.id) - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_form-2-name">Name:</label> <input id="id_form-2-name" type="text" name="form-2-name" maxlength="100" /><input type="hidden" name="form-2-id" id="id_form-2-id" /></p>') - - data = { - 'form-TOTAL_FORMS': '3', # the number of forms rendered - 'form-INITIAL_FORMS': '2', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-id': str(author2.id), - 'form-0-name': 'Arthur Rimbaud', - 'form-1-id': str(author1.id), - 'form-1-name': 'Charles Baudelaire', - 'form-2-name': 'Paul Verlaine', - } - - formset = AuthorFormSet(data=data, queryset=qs) - self.assertTrue(formset.is_valid()) - - # Only changed or new objects are returned from formset.save() - saved = formset.save() - self.assertEqual(len(saved), 1) - author3 = saved[0] - self.assertEqual(author3, Author.objects.get(name='Paul Verlaine')) - - authors = list(Author.objects.order_by('name')) - self.assertEqual(authors, [author2, author1, author3]) - - # This probably shouldn't happen, but it will. If an add form was - # marked for deletion, make sure we don't save that form. - - qs = Author.objects.order_by('name') - AuthorFormSet = modelformset_factory(Author, extra=1, can_delete=True) - - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 4) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" value="Arthur Rimbaud" maxlength="100" /></p>\n' - '<p><label for="id_form-0-DELETE">Delete:</label> <input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE" /><input type="hidden" name="form-0-id" value="%d" id="id_form-0-id" /></p>' % author2.id) - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_form-1-name">Name:</label> <input id="id_form-1-name" type="text" name="form-1-name" value="Charles Baudelaire" maxlength="100" /></p>\n' - '<p><label for="id_form-1-DELETE">Delete:</label> <input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE" /><input type="hidden" name="form-1-id" value="%d" id="id_form-1-id" /></p>' % author1.id) - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_form-2-name">Name:</label> <input id="id_form-2-name" type="text" name="form-2-name" value="Paul Verlaine" maxlength="100" /></p>\n' - '<p><label for="id_form-2-DELETE">Delete:</label> <input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" /><input type="hidden" name="form-2-id" value="%d" id="id_form-2-id" /></p>' % author3.id) - self.assertEqual(formset.forms[3].as_p(), - '<p><label for="id_form-3-name">Name:</label> <input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /></p>\n' - '<p><label for="id_form-3-DELETE">Delete:</label> <input type="checkbox" name="form-3-DELETE" id="id_form-3-DELETE" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></p>') - - data = { - 'form-TOTAL_FORMS': '4', # the number of forms rendered - 'form-INITIAL_FORMS': '3', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-id': str(author2.id), - 'form-0-name': 'Arthur Rimbaud', - 'form-1-id': str(author1.id), - 'form-1-name': 'Charles Baudelaire', - 'form-2-id': str(author3.id), - 'form-2-name': 'Paul Verlaine', - 'form-3-name': 'Walt Whitman', - 'form-3-DELETE': 'on', - } - - formset = AuthorFormSet(data=data, queryset=qs) - self.assertTrue(formset.is_valid()) - - # No objects were changed or saved so nothing will come back. - - self.assertEqual(formset.save(), []) - - authors = list(Author.objects.order_by('name')) - self.assertEqual(authors, [author2, author1, author3]) - - # Let's edit a record to ensure save only returns that one record. - - data = { - 'form-TOTAL_FORMS': '4', # the number of forms rendered - 'form-INITIAL_FORMS': '3', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-id': str(author2.id), - 'form-0-name': 'Walt Whitman', - 'form-1-id': str(author1.id), - 'form-1-name': 'Charles Baudelaire', - 'form-2-id': str(author3.id), - 'form-2-name': 'Paul Verlaine', - 'form-3-name': '', - 'form-3-DELETE': '', - } - - formset = AuthorFormSet(data=data, queryset=qs) - self.assertTrue(formset.is_valid()) - - # One record has changed. - - saved = formset.save() - self.assertEqual(len(saved), 1) - self.assertEqual(saved[0], Author.objects.get(name='Walt Whitman')) - - def test_commit_false(self): - # Test the behavior of commit=False and save_m2m - - author1 = Author.objects.create(name='Charles Baudelaire') - author2 = Author.objects.create(name='Paul Verlaine') - author3 = Author.objects.create(name='Walt Whitman') - - meeting = AuthorMeeting.objects.create(created=date.today()) - meeting.authors = Author.objects.all() - - # create an Author instance to add to the meeting. - - author4 = Author.objects.create(name=u'John Steinbeck') - - AuthorMeetingFormSet = modelformset_factory(AuthorMeeting, extra=1, can_delete=True) - data = { - 'form-TOTAL_FORMS': '2', # the number of forms rendered - 'form-INITIAL_FORMS': '1', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-id': '1', - 'form-0-name': '2nd Tuesday of the Week Meeting', - 'form-0-authors': [2, 1, 3, 4], - 'form-1-name': '', - 'form-1-authors': '', - 'form-1-DELETE': '', - } - formset = AuthorMeetingFormSet(data=data, queryset=AuthorMeeting.objects.all()) - self.assertTrue(formset.is_valid()) - - instances = formset.save(commit=False) - for instance in instances: - instance.created = date.today() - instance.save() - formset.save_m2m() - self.assertQuerysetEqual(instances[0].authors.all(), [ - '<Author: Charles Baudelaire>', - '<Author: John Steinbeck>', - '<Author: Paul Verlaine>', - '<Author: Walt Whitman>', - ]) - - def test_max_num(self): - # Test the behavior of max_num with model formsets. It should allow - # all existing related objects/inlines for a given object to be - # displayed, but not allow the creation of new inlines beyond max_num. - - author1 = Author.objects.create(name='Charles Baudelaire') - author2 = Author.objects.create(name='Paul Verlaine') - author3 = Author.objects.create(name='Walt Whitman') - - qs = Author.objects.order_by('name') - - AuthorFormSet = modelformset_factory(Author, max_num=None, extra=3) - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 6) - self.assertEqual(len(formset.extra_forms), 3) - - AuthorFormSet = modelformset_factory(Author, max_num=4, extra=3) - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 4) - self.assertEqual(len(formset.extra_forms), 1) - - AuthorFormSet = modelformset_factory(Author, max_num=0, extra=3) - formset = AuthorFormSet(queryset=qs) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(len(formset.extra_forms), 0) - - AuthorFormSet = modelformset_factory(Author, max_num=None) - formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '<Author: Charles Baudelaire>', - '<Author: Paul Verlaine>', - '<Author: Walt Whitman>', - ]) - - AuthorFormSet = modelformset_factory(Author, max_num=0) - formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '<Author: Charles Baudelaire>', - '<Author: Paul Verlaine>', - '<Author: Walt Whitman>', - ]) - - AuthorFormSet = modelformset_factory(Author, max_num=4) - formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '<Author: Charles Baudelaire>', - '<Author: Paul Verlaine>', - '<Author: Walt Whitman>', - ]) - - def test_custom_save_method(self): - class PoetForm(forms.ModelForm): - def save(self, commit=True): - # change the name to "Vladimir Mayakovsky" just to be a jerk. - author = super(PoetForm, self).save(commit=False) - author.name = u"Vladimir Mayakovsky" - if commit: - author.save() - return author - - PoetFormSet = modelformset_factory(Poet, form=PoetForm) - - data = { - 'form-TOTAL_FORMS': '3', # the number of forms rendered - 'form-INITIAL_FORMS': '0', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-name': 'Walt Whitman', - 'form-1-name': 'Charles Baudelaire', - 'form-2-name': '', - } - - qs = Poet.objects.all() - formset = PoetFormSet(data=data, queryset=qs) - self.assertTrue(formset.is_valid()) - - poets = formset.save() - self.assertEqual(len(poets), 2) - poet1, poet2 = poets - self.assertEqual(poet1.name, 'Vladimir Mayakovsky') - self.assertEqual(poet2.name, 'Vladimir Mayakovsky') - - def test_model_inheritance(self): - BetterAuthorFormSet = modelformset_factory(BetterAuthor) - formset = BetterAuthorFormSet() - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></p>\n' - '<p><label for="id_form-0-write_speed">Write speed:</label> <input type="text" name="form-0-write_speed" id="id_form-0-write_speed" /><input type="hidden" name="form-0-author_ptr" id="id_form-0-author_ptr" /></p>') - - data = { - 'form-TOTAL_FORMS': '1', # the number of forms rendered - 'form-INITIAL_FORMS': '0', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-author_ptr': '', - 'form-0-name': 'Ernest Hemingway', - 'form-0-write_speed': '10', - } - - formset = BetterAuthorFormSet(data) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - author1, = saved - self.assertEqual(author1, BetterAuthor.objects.get(name='Ernest Hemingway')) - hemingway_id = BetterAuthor.objects.get(name="Ernest Hemingway").pk - - formset = BetterAuthorFormSet() - self.assertEqual(len(formset.forms), 2) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-name">Name:</label> <input id="id_form-0-name" type="text" name="form-0-name" value="Ernest Hemingway" maxlength="100" /></p>\n' - '<p><label for="id_form-0-write_speed">Write speed:</label> <input type="text" name="form-0-write_speed" value="10" id="id_form-0-write_speed" /><input type="hidden" name="form-0-author_ptr" value="%d" id="id_form-0-author_ptr" /></p>' % hemingway_id) - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_form-1-name">Name:</label> <input id="id_form-1-name" type="text" name="form-1-name" maxlength="100" /></p>\n' - '<p><label for="id_form-1-write_speed">Write speed:</label> <input type="text" name="form-1-write_speed" id="id_form-1-write_speed" /><input type="hidden" name="form-1-author_ptr" id="id_form-1-author_ptr" /></p>') - - data = { - 'form-TOTAL_FORMS': '2', # the number of forms rendered - 'form-INITIAL_FORMS': '1', # the number of forms with initial data - 'form-MAX_NUM_FORMS': '', # the max number of forms - 'form-0-author_ptr': hemingway_id, - 'form-0-name': 'Ernest Hemingway', - 'form-0-write_speed': '10', - 'form-1-author_ptr': '', - 'form-1-name': '', - 'form-1-write_speed': '', - } - - formset = BetterAuthorFormSet(data) - self.assertTrue(formset.is_valid()) - self.assertEqual(formset.save(), []) - - def test_inline_formsets(self): - # We can also create a formset that is tied to a parent model. This is - # how the admin system's edit inline functionality works. - - AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=3) - author = Author.objects.create(name='Charles Baudelaire') - - formset = AuthorBooksFormSet(instance=author) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" maxlength="100" /><input type="hidden" name="book_set-0-author" value="%d" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" id="id_book_set-0-id" /></p>' % author.id) - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-author" value="%d" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>' % author.id) - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-author" value="%d" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>' % author.id) - - data = { - 'book_set-TOTAL_FORMS': '3', # the number of forms rendered - 'book_set-INITIAL_FORMS': '0', # the number of forms with initial data - 'book_set-MAX_NUM_FORMS': '', # the max number of forms - 'book_set-0-title': 'Les Fleurs du Mal', - 'book_set-1-title': '', - 'book_set-2-title': '', - } - - formset = AuthorBooksFormSet(data, instance=author) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 1) - book1, = saved - self.assertEqual(book1, Book.objects.get(title='Les Fleurs du Mal')) - self.assertQuerysetEqual(author.book_set.all(), ['<Book: Les Fleurs du Mal>']) - - # Now that we've added a book to Charles Baudelaire, let's try adding - # another one. This time though, an edit form will be available for - # every existing book. - - AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=2) - author = Author.objects.get(name='Charles Baudelaire') - - formset = AuthorBooksFormSet(instance=author) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" value="Les Fleurs du Mal" maxlength="100" /><input type="hidden" name="book_set-0-author" value="%d" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" value="%d" id="id_book_set-0-id" /></p>' % (author.id, book1.id)) - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-author" value="%d" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>' % author.id) - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-author" value="%d" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>' % author.id) - - data = { - 'book_set-TOTAL_FORMS': '3', # the number of forms rendered - 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data - 'book_set-MAX_NUM_FORMS': '', # the max number of forms - 'book_set-0-id': '1', - 'book_set-0-title': 'Les Fleurs du Mal', - 'book_set-1-title': 'Les Paradis Artificiels', - 'book_set-2-title': '', - } - - formset = AuthorBooksFormSet(data, instance=author) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 1) - book2, = saved - self.assertEqual(book2, Book.objects.get(title='Les Paradis Artificiels')) - - # As you can see, 'Les Paradis Artificiels' is now a book belonging to - # Charles Baudelaire. - self.assertQuerysetEqual(author.book_set.order_by('title'), [ - '<Book: Les Fleurs du Mal>', - '<Book: Les Paradis Artificiels>', - ]) - - def test_inline_formsets_save_as_new(self): - # The save_as_new parameter lets you re-associate the data to a new - # instance. This is used in the admin for save_as functionality. - AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=2) - author = Author.objects.create(name='Charles Baudelaire') - - data = { - 'book_set-TOTAL_FORMS': '3', # the number of forms rendered - 'book_set-INITIAL_FORMS': '2', # the number of forms with initial data - 'book_set-MAX_NUM_FORMS': '', # the max number of forms - 'book_set-0-id': '1', - 'book_set-0-title': 'Les Fleurs du Mal', - 'book_set-1-id': '2', - 'book_set-1-title': 'Les Paradis Artificiels', - 'book_set-2-title': '', - } - - formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True) - self.assertTrue(formset.is_valid()) - - new_author = Author.objects.create(name='Charles Baudelaire') - formset = AuthorBooksFormSet(data, instance=new_author, save_as_new=True) - saved = formset.save() - self.assertEqual(len(saved), 2) - book1, book2 = saved - self.assertEqual(book1.title, 'Les Fleurs du Mal') - self.assertEqual(book2.title, 'Les Paradis Artificiels') - - # Test using a custom prefix on an inline formset. - - formset = AuthorBooksFormSet(prefix="test") - self.assertEqual(len(formset.forms), 2) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_test-0-title">Title:</label> <input id="id_test-0-title" type="text" name="test-0-title" maxlength="100" /><input type="hidden" name="test-0-author" id="id_test-0-author" /><input type="hidden" name="test-0-id" id="id_test-0-id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_test-1-title">Title:</label> <input id="id_test-1-title" type="text" name="test-1-title" maxlength="100" /><input type="hidden" name="test-1-author" id="id_test-1-author" /><input type="hidden" name="test-1-id" id="id_test-1-id" /></p>') - - def test_inline_formsets_with_custom_pk(self): - # Test inline formsets where the inline-edited object has a custom - # primary key that is not the fk to the parent object. - - AuthorBooksFormSet2 = inlineformset_factory(Author, BookWithCustomPK, can_delete=False, extra=1) - author = Author.objects.create(pk=1, name='Charles Baudelaire') - - formset = AuthorBooksFormSet2(instance=author) - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_bookwithcustompk_set-0-my_pk">My pk:</label> <input type="text" name="bookwithcustompk_set-0-my_pk" id="id_bookwithcustompk_set-0-my_pk" /></p>\n' - '<p><label for="id_bookwithcustompk_set-0-title">Title:</label> <input id="id_bookwithcustompk_set-0-title" type="text" name="bookwithcustompk_set-0-title" maxlength="100" /><input type="hidden" name="bookwithcustompk_set-0-author" value="1" id="id_bookwithcustompk_set-0-author" /></p>') - - data = { - 'bookwithcustompk_set-TOTAL_FORMS': '1', # the number of forms rendered - 'bookwithcustompk_set-INITIAL_FORMS': '0', # the number of forms with initial data - 'bookwithcustompk_set-MAX_NUM_FORMS': '', # the max number of forms - 'bookwithcustompk_set-0-my_pk': '77777', - 'bookwithcustompk_set-0-title': 'Les Fleurs du Mal', - } - - formset = AuthorBooksFormSet2(data, instance=author) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 1) - book1, = saved - self.assertEqual(book1.pk, 77777) - - book1 = author.bookwithcustompk_set.get() - self.assertEqual(book1.title, 'Les Fleurs du Mal') - - def test_inline_formsets_with_multi_table_inheritance(self): - # Test inline formsets where the inline-edited object uses multi-table - # inheritance, thus has a non AutoField yet auto-created primary key. - - AuthorBooksFormSet3 = inlineformset_factory(Author, AlternateBook, can_delete=False, extra=1) - author = Author.objects.create(pk=1, name='Charles Baudelaire') - - formset = AuthorBooksFormSet3(instance=author) - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_alternatebook_set-0-title">Title:</label> <input id="id_alternatebook_set-0-title" type="text" name="alternatebook_set-0-title" maxlength="100" /></p>\n' - '<p><label for="id_alternatebook_set-0-notes">Notes:</label> <input id="id_alternatebook_set-0-notes" type="text" name="alternatebook_set-0-notes" maxlength="100" /><input type="hidden" name="alternatebook_set-0-author" value="1" id="id_alternatebook_set-0-author" /><input type="hidden" name="alternatebook_set-0-book_ptr" id="id_alternatebook_set-0-book_ptr" /></p>') - - data = { - 'alternatebook_set-TOTAL_FORMS': '1', # the number of forms rendered - 'alternatebook_set-INITIAL_FORMS': '0', # the number of forms with initial data - 'alternatebook_set-MAX_NUM_FORMS': '', # the max number of forms - 'alternatebook_set-0-title': 'Flowers of Evil', - 'alternatebook_set-0-notes': 'English translation of Les Fleurs du Mal' - } - - formset = AuthorBooksFormSet3(data, instance=author) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 1) - book1, = saved - self.assertEqual(book1.title, 'Flowers of Evil') - self.assertEqual(book1.notes, 'English translation of Les Fleurs du Mal') - - # Test inline formsets where the inline-edited object has a - # unique_together constraint with a nullable member - - AuthorBooksFormSet4 = inlineformset_factory(Author, BookWithOptionalAltEditor, can_delete=False, extra=2) - - data = { - 'bookwithoptionalalteditor_set-TOTAL_FORMS': '2', # the number of forms rendered - 'bookwithoptionalalteditor_set-INITIAL_FORMS': '0', # the number of forms with initial data - 'bookwithoptionalalteditor_set-MAX_NUM_FORMS': '', # the max number of forms - 'bookwithoptionalalteditor_set-0-author': '1', - 'bookwithoptionalalteditor_set-0-title': 'Les Fleurs du Mal', - 'bookwithoptionalalteditor_set-1-author': '1', - 'bookwithoptionalalteditor_set-1-title': 'Les Fleurs du Mal', - } - formset = AuthorBooksFormSet4(data, instance=author) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 2) - book1, book2 = saved - self.assertEqual(book1.author_id, 1) - self.assertEqual(book1.title, 'Les Fleurs du Mal') - self.assertEqual(book2.author_id, 1) - self.assertEqual(book2.title, 'Les Fleurs du Mal') - - def test_inline_formsets_with_custom_save_method(self): - AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=2) - author = Author.objects.create(pk=1, name='Charles Baudelaire') - book1 = Book.objects.create(pk=1, author=author, title='Les Paradis Artificiels') - book2 = Book.objects.create(pk=2, author=author, title='Les Fleurs du Mal') - book3 = Book.objects.create(pk=3, author=author, title='Flowers of Evil') - - class PoemForm(forms.ModelForm): - def save(self, commit=True): - # change the name to "Brooklyn Bridge" just to be a jerk. - poem = super(PoemForm, self).save(commit=False) - poem.name = u"Brooklyn Bridge" - if commit: - poem.save() - return poem - - PoemFormSet = inlineformset_factory(Poet, Poem, form=PoemForm) - - data = { - 'poem_set-TOTAL_FORMS': '3', # the number of forms rendered - 'poem_set-INITIAL_FORMS': '0', # the number of forms with initial data - 'poem_set-MAX_NUM_FORMS': '', # the max number of forms - 'poem_set-0-name': 'The Cloud in Trousers', - 'poem_set-1-name': 'I', - 'poem_set-2-name': '', - } - - poet = Poet.objects.create(name='Vladimir Mayakovsky') - formset = PoemFormSet(data=data, instance=poet) - self.assertTrue(formset.is_valid()) - - saved = formset.save() - self.assertEqual(len(saved), 2) - poem1, poem2 = saved - self.assertEqual(poem1.name, 'Brooklyn Bridge') - self.assertEqual(poem2.name, 'Brooklyn Bridge') - - # We can provide a custom queryset to our InlineFormSet: - - custom_qs = Book.objects.order_by('-title') - formset = AuthorBooksFormSet(instance=author, queryset=custom_qs) - self.assertEqual(len(formset.forms), 5) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" value="Les Paradis Artificiels" maxlength="100" /><input type="hidden" name="book_set-0-author" value="1" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" value="1" id="id_book_set-0-id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" value="Les Fleurs du Mal" maxlength="100" /><input type="hidden" name="book_set-1-author" value="1" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" value="2" id="id_book_set-1-id" /></p>') - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" value="Flowers of Evil" maxlength="100" /><input type="hidden" name="book_set-2-author" value="1" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" value="3" id="id_book_set-2-id" /></p>') - self.assertEqual(formset.forms[3].as_p(), - '<p><label for="id_book_set-3-title">Title:</label> <input id="id_book_set-3-title" type="text" name="book_set-3-title" maxlength="100" /><input type="hidden" name="book_set-3-author" value="1" id="id_book_set-3-author" /><input type="hidden" name="book_set-3-id" id="id_book_set-3-id" /></p>') - self.assertEqual(formset.forms[4].as_p(), - '<p><label for="id_book_set-4-title">Title:</label> <input id="id_book_set-4-title" type="text" name="book_set-4-title" maxlength="100" /><input type="hidden" name="book_set-4-author" value="1" id="id_book_set-4-author" /><input type="hidden" name="book_set-4-id" id="id_book_set-4-id" /></p>') - - data = { - 'book_set-TOTAL_FORMS': '5', # the number of forms rendered - 'book_set-INITIAL_FORMS': '3', # the number of forms with initial data - 'book_set-MAX_NUM_FORMS': '', # the max number of forms - 'book_set-0-id': str(book1.id), - 'book_set-0-title': 'Les Paradis Artificiels', - 'book_set-1-id': str(book2.id), - 'book_set-1-title': 'Les Fleurs du Mal', - 'book_set-2-id': str(book3.id), - 'book_set-2-title': 'Flowers of Evil', - 'book_set-3-title': 'Revue des deux mondes', - 'book_set-4-title': '', - } - formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) - self.assertTrue(formset.is_valid()) - - custom_qs = Book.objects.filter(title__startswith='F') - formset = AuthorBooksFormSet(instance=author, queryset=custom_qs) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_book_set-0-title">Title:</label> <input id="id_book_set-0-title" type="text" name="book_set-0-title" value="Flowers of Evil" maxlength="100" /><input type="hidden" name="book_set-0-author" value="1" id="id_book_set-0-author" /><input type="hidden" name="book_set-0-id" value="3" id="id_book_set-0-id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_book_set-1-title">Title:</label> <input id="id_book_set-1-title" type="text" name="book_set-1-title" maxlength="100" /><input type="hidden" name="book_set-1-author" value="1" id="id_book_set-1-author" /><input type="hidden" name="book_set-1-id" id="id_book_set-1-id" /></p>') - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_book_set-2-title">Title:</label> <input id="id_book_set-2-title" type="text" name="book_set-2-title" maxlength="100" /><input type="hidden" name="book_set-2-author" value="1" id="id_book_set-2-author" /><input type="hidden" name="book_set-2-id" id="id_book_set-2-id" /></p>') - - data = { - 'book_set-TOTAL_FORMS': '3', # the number of forms rendered - 'book_set-INITIAL_FORMS': '1', # the number of forms with initial data - 'book_set-MAX_NUM_FORMS': '', # the max number of forms - 'book_set-0-id': str(book3.id), - 'book_set-0-title': 'Flowers of Evil', - 'book_set-1-title': 'Revue des deux mondes', - 'book_set-2-title': '', - } - formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) - self.assertTrue(formset.is_valid()) - - def test_custom_pk(self): - # We need to ensure that it is displayed - - CustomPrimaryKeyFormSet = modelformset_factory(CustomPrimaryKey) - formset = CustomPrimaryKeyFormSet() - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-my_pk">My pk:</label> <input id="id_form-0-my_pk" type="text" name="form-0-my_pk" maxlength="10" /></p>\n' - '<p><label for="id_form-0-some_field">Some field:</label> <input id="id_form-0-some_field" type="text" name="form-0-some_field" maxlength="100" /></p>') - - # Custom primary keys with ForeignKey, OneToOneField and AutoField ############ - - place = Place.objects.create(pk=1, name=u'Giordanos', city=u'Chicago') - - FormSet = inlineformset_factory(Place, Owner, extra=2, can_delete=False) - formset = FormSet(instance=place) - self.assertEqual(len(formset.forms), 2) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" maxlength="100" /><input type="hidden" name="owner_set-0-place" value="1" id="id_owner_set-0-place" /><input type="hidden" name="owner_set-0-auto_id" id="id_owner_set-0-auto_id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-place" value="1" id="id_owner_set-1-place" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>') - - data = { - 'owner_set-TOTAL_FORMS': '2', - 'owner_set-INITIAL_FORMS': '0', - 'owner_set-MAX_NUM_FORMS': '', - 'owner_set-0-auto_id': '', - 'owner_set-0-name': u'Joe Perry', - 'owner_set-1-auto_id': '', - 'owner_set-1-name': '', - } - formset = FormSet(data, instance=place) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - owner, = saved - self.assertEqual(owner.name, 'Joe Perry') - self.assertEqual(owner.place.name, 'Giordanos') - - formset = FormSet(instance=place) - self.assertEqual(len(formset.forms), 3) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_owner_set-0-name">Name:</label> <input id="id_owner_set-0-name" type="text" name="owner_set-0-name" value="Joe Perry" maxlength="100" /><input type="hidden" name="owner_set-0-place" value="1" id="id_owner_set-0-place" /><input type="hidden" name="owner_set-0-auto_id" value="1" id="id_owner_set-0-auto_id" /></p>') - self.assertEqual(formset.forms[1].as_p(), - '<p><label for="id_owner_set-1-name">Name:</label> <input id="id_owner_set-1-name" type="text" name="owner_set-1-name" maxlength="100" /><input type="hidden" name="owner_set-1-place" value="1" id="id_owner_set-1-place" /><input type="hidden" name="owner_set-1-auto_id" id="id_owner_set-1-auto_id" /></p>') - self.assertEqual(formset.forms[2].as_p(), - '<p><label for="id_owner_set-2-name">Name:</label> <input id="id_owner_set-2-name" type="text" name="owner_set-2-name" maxlength="100" /><input type="hidden" name="owner_set-2-place" value="1" id="id_owner_set-2-place" /><input type="hidden" name="owner_set-2-auto_id" id="id_owner_set-2-auto_id" /></p>') - - data = { - 'owner_set-TOTAL_FORMS': '3', - 'owner_set-INITIAL_FORMS': '1', - 'owner_set-MAX_NUM_FORMS': '', - 'owner_set-0-auto_id': u'1', - 'owner_set-0-name': u'Joe Perry', - 'owner_set-1-auto_id': '', - 'owner_set-1-name': u'Jack Berry', - 'owner_set-2-auto_id': '', - 'owner_set-2-name': '', - } - formset = FormSet(data, instance=place) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - owner, = saved - self.assertEqual(owner.name, 'Jack Berry') - self.assertEqual(owner.place.name, 'Giordanos') - - # Ensure a custom primary key that is a ForeignKey or OneToOneField get rendered for the user to choose. - - FormSet = modelformset_factory(OwnerProfile) - formset = FormSet() - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_form-0-owner">Owner:</label> <select name="form-0-owner" id="id_form-0-owner">\n' - '<option value="" selected="selected">---------</option>\n' - '<option value="1">Joe Perry at Giordanos</option>\n' - '<option value="2">Jack Berry at Giordanos</option>\n' - '</select></p>\n' - '<p><label for="id_form-0-age">Age:</label> <input type="text" name="form-0-age" id="id_form-0-age" /></p>') - - owner = Owner.objects.get(name=u'Joe Perry') - FormSet = inlineformset_factory(Owner, OwnerProfile, max_num=1, can_delete=False) - self.assertEqual(FormSet.max_num, 1) - - formset = FormSet(instance=owner) - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_ownerprofile-0-age">Age:</label> <input type="text" name="ownerprofile-0-age" id="id_ownerprofile-0-age" /><input type="hidden" name="ownerprofile-0-owner" value="1" id="id_ownerprofile-0-owner" /></p>') - - data = { - 'ownerprofile-TOTAL_FORMS': '1', - 'ownerprofile-INITIAL_FORMS': '0', - 'ownerprofile-MAX_NUM_FORMS': '1', - 'ownerprofile-0-owner': '', - 'ownerprofile-0-age': u'54', - } - formset = FormSet(data, instance=owner) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - profile1, = saved - self.assertEqual(profile1.owner, owner) - self.assertEqual(profile1.age, 54) - - formset = FormSet(instance=owner) - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_ownerprofile-0-age">Age:</label> <input type="text" name="ownerprofile-0-age" value="54" id="id_ownerprofile-0-age" /><input type="hidden" name="ownerprofile-0-owner" value="1" id="id_ownerprofile-0-owner" /></p>') - - data = { - 'ownerprofile-TOTAL_FORMS': '1', - 'ownerprofile-INITIAL_FORMS': '1', - 'ownerprofile-MAX_NUM_FORMS': '1', - 'ownerprofile-0-owner': u'1', - 'ownerprofile-0-age': u'55', - } - formset = FormSet(data, instance=owner) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - profile1, = saved - self.assertEqual(profile1.owner, owner) - self.assertEqual(profile1.age, 55) - - def test_unique_true_enforces_max_num_one(self): - # ForeignKey with unique=True should enforce max_num=1 - - place = Place.objects.create(pk=1, name=u'Giordanos', city=u'Chicago') - - FormSet = inlineformset_factory(Place, Location, can_delete=False) - self.assertEqual(FormSet.max_num, 1) - - formset = FormSet(instance=place) - self.assertEqual(len(formset.forms), 1) - self.assertEqual(formset.forms[0].as_p(), - '<p><label for="id_location_set-0-lat">Lat:</label> <input id="id_location_set-0-lat" type="text" name="location_set-0-lat" maxlength="100" /></p>\n' - '<p><label for="id_location_set-0-lon">Lon:</label> <input id="id_location_set-0-lon" type="text" name="location_set-0-lon" maxlength="100" /><input type="hidden" name="location_set-0-place" value="1" id="id_location_set-0-place" /><input type="hidden" name="location_set-0-id" id="id_location_set-0-id" /></p>') - - def test_foreign_keys_in_parents(self): - self.assertEqual(type(_get_foreign_key(Restaurant, Owner)), models.ForeignKey) - self.assertEqual(type(_get_foreign_key(MexicanRestaurant, Owner)), models.ForeignKey) - - def test_unique_validation(self): - FormSet = modelformset_factory(Product, extra=1) - data = { - 'form-TOTAL_FORMS': '1', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - 'form-0-slug': 'car-red', - } - formset = FormSet(data) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - product1, = saved - self.assertEqual(product1.slug, 'car-red') - - data = { - 'form-TOTAL_FORMS': '1', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - 'form-0-slug': 'car-red', - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset.errors, [{'slug': [u'Product with this Slug already exists.']}]) - - def test_unique_together_validation(self): - FormSet = modelformset_factory(Price, extra=1) - data = { - 'form-TOTAL_FORMS': '1', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - 'form-0-price': u'12.00', - 'form-0-quantity': '1', - } - formset = FormSet(data) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - price1, = saved - self.assertEqual(price1.price, Decimal('12.00')) - self.assertEqual(price1.quantity, 1) - - data = { - 'form-TOTAL_FORMS': '1', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - 'form-0-price': u'12.00', - 'form-0-quantity': '1', - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset.errors, [{'__all__': [u'Price with this Price and Quantity already exists.']}]) - - def test_unique_together_with_inlineformset_factory(self): - # Also see bug #8882. - - repository = Repository.objects.create(name=u'Test Repo') - FormSet = inlineformset_factory(Repository, Revision, extra=1) - data = { - 'revision_set-TOTAL_FORMS': '1', - 'revision_set-INITIAL_FORMS': '0', - 'revision_set-MAX_NUM_FORMS': '', - 'revision_set-0-repository': repository.pk, - 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', - 'revision_set-0-DELETE': '', - } - formset = FormSet(data, instance=repository) - self.assertTrue(formset.is_valid()) - saved = formset.save() - self.assertEqual(len(saved), 1) - revision1, = saved - self.assertEqual(revision1.repository, repository) - self.assertEqual(revision1.revision, '146239817507f148d448db38840db7c3cbf47c76') - - # attempt to save the same revision against against the same repo. - data = { - 'revision_set-TOTAL_FORMS': '1', - 'revision_set-INITIAL_FORMS': '0', - 'revision_set-MAX_NUM_FORMS': '', - 'revision_set-0-repository': repository.pk, - 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', - 'revision_set-0-DELETE': '', - } - formset = FormSet(data, instance=repository) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset.errors, [{'__all__': [u'Revision with this Repository and Revision already exists.']}]) - - # unique_together with inlineformset_factory with overridden form fields - # Also see #9494 - - FormSet = inlineformset_factory(Repository, Revision, fields=('revision',), extra=1) - data = { - 'revision_set-TOTAL_FORMS': '1', - 'revision_set-INITIAL_FORMS': '0', - 'revision_set-MAX_NUM_FORMS': '', - 'revision_set-0-repository': repository.pk, - 'revision_set-0-revision': '146239817507f148d448db38840db7c3cbf47c76', - 'revision_set-0-DELETE': '', - } - formset = FormSet(data, instance=repository) - self.assertFalse(formset.is_valid()) - - def test_callable_defaults(self): - # Use of callable defaults (see bug #7975). - - person = Person.objects.create(name='Ringo') - FormSet = inlineformset_factory(Person, Membership, can_delete=False, extra=1) - formset = FormSet(instance=person) - - # Django will render a hidden field for model fields that have a callable - # default. This is required to ensure the value is tested for change correctly - # when determine what extra forms have changed to save. - - self.assertEquals(len(formset.forms), 1) # this formset only has one form - form = formset.forms[0] - now = form.fields['date_joined'].initial() - result = form.as_p() - result = re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?', '__DATETIME__', result) - self.assertEqual(result, - '<p><label for="id_membership_set-0-date_joined">Date joined:</label> <input type="text" name="membership_set-0-date_joined" value="__DATETIME__" id="id_membership_set-0-date_joined" /><input type="hidden" name="initial-membership_set-0-date_joined" value="__DATETIME__" id="initial-membership_set-0-id_membership_set-0-date_joined" /></p>\n' - '<p><label for="id_membership_set-0-karma">Karma:</label> <input type="text" name="membership_set-0-karma" id="id_membership_set-0-karma" /><input type="hidden" name="membership_set-0-person" value="1" id="id_membership_set-0-person" /><input type="hidden" name="membership_set-0-id" id="id_membership_set-0-id" /></p>') - - # test for validation with callable defaults. Validations rely on hidden fields - - data = { - 'membership_set-TOTAL_FORMS': '1', - 'membership_set-INITIAL_FORMS': '0', - 'membership_set-MAX_NUM_FORMS': '', - 'membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), - 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), - 'membership_set-0-karma': '', - } - formset = FormSet(data, instance=person) - self.assertTrue(formset.is_valid()) - - # now test for when the data changes - - one_day_later = now + datetime.timedelta(days=1) - filled_data = { - 'membership_set-TOTAL_FORMS': '1', - 'membership_set-INITIAL_FORMS': '0', - 'membership_set-MAX_NUM_FORMS': '', - 'membership_set-0-date_joined': unicode(one_day_later.strftime('%Y-%m-%d %H:%M:%S')), - 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), - 'membership_set-0-karma': '', - } - formset = FormSet(filled_data, instance=person) - self.assertFalse(formset.is_valid()) - - # now test with split datetime fields - - class MembershipForm(forms.ModelForm): - date_joined = forms.SplitDateTimeField(initial=now) - class Meta: - model = Membership - def __init__(self, **kwargs): - super(MembershipForm, self).__init__(**kwargs) - self.fields['date_joined'].widget = forms.SplitDateTimeWidget() - - FormSet = inlineformset_factory(Person, Membership, form=MembershipForm, can_delete=False, extra=1) - data = { - 'membership_set-TOTAL_FORMS': '1', - 'membership_set-INITIAL_FORMS': '0', - 'membership_set-MAX_NUM_FORMS': '', - 'membership_set-0-date_joined_0': unicode(now.strftime('%Y-%m-%d')), - 'membership_set-0-date_joined_1': unicode(now.strftime('%H:%M:%S')), - 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')), - 'membership_set-0-karma': '', - } - formset = FormSet(data, instance=person) - self.assertTrue(formset.is_valid()) - - def test_inlineformset_factory_with_null_fk(self): - # inlineformset_factory tests with fk having null=True. see #9462. - # create some data that will exbit the issue - team = Team.objects.create(name=u"Red Vipers") - Player(name="Timmy").save() - Player(name="Bobby", team=team).save() - - PlayerInlineFormSet = inlineformset_factory(Team, Player) - formset = PlayerInlineFormSet() - self.assertQuerysetEqual(formset.get_queryset(), []) - - formset = PlayerInlineFormSet(instance=team) - players = formset.get_queryset() - self.assertEqual(len(players), 1) - player1, = players - self.assertEqual(player1.team, team) - self.assertEqual(player1.name, 'Bobby') - - def test_model_formset_with_custom_pk(self): - # a formset for a Model that has a custom primary key that still needs to be - # added to the formset automatically - FormSet = modelformset_factory(ClassyMexicanRestaurant, fields=["tacos_are_yummy"]) - self.assertEqual(sorted(FormSet().forms[0].fields.keys()), ['restaurant', 'tacos_are_yummy']) - - def test_prevent_duplicates_from_with_the_same_formset(self): - FormSet = modelformset_factory(Product, extra=2) - data = { - 'form-TOTAL_FORMS': 2, - 'form-INITIAL_FORMS': 0, - 'form-MAX_NUM_FORMS': '', - 'form-0-slug': 'red_car', - 'form-1-slug': 'red_car', - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for slug.']) - - FormSet = modelformset_factory(Price, extra=2) - data = { - 'form-TOTAL_FORMS': 2, - 'form-INITIAL_FORMS': 0, - 'form-MAX_NUM_FORMS': '', - 'form-0-price': '25', - 'form-0-quantity': '7', - 'form-1-price': '25', - 'form-1-quantity': '7', - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for price and quantity, which must be unique.']) - - # Only the price field is specified, this should skip any unique checks since - # the unique_together is not fulfilled. This will fail with a KeyError if broken. - FormSet = modelformset_factory(Price, fields=("price",), extra=2) - data = { - 'form-TOTAL_FORMS': '2', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - 'form-0-price': '24', - 'form-1-price': '24', - } - formset = FormSet(data) - self.assertTrue(formset.is_valid()) - - FormSet = inlineformset_factory(Author, Book, extra=0) - author = Author.objects.create(pk=1, name='Charles Baudelaire') - book1 = Book.objects.create(pk=1, author=author, title='Les Paradis Artificiels') - book2 = Book.objects.create(pk=2, author=author, title='Les Fleurs du Mal') - book3 = Book.objects.create(pk=3, author=author, title='Flowers of Evil') - - book_ids = author.book_set.order_by('id').values_list('id', flat=True) - data = { - 'book_set-TOTAL_FORMS': '2', - 'book_set-INITIAL_FORMS': '2', - 'book_set-MAX_NUM_FORMS': '', - - 'book_set-0-title': 'The 2008 Election', - 'book_set-0-author': str(author.id), - 'book_set-0-id': str(book_ids[0]), - - 'book_set-1-title': 'The 2008 Election', - 'book_set-1-author': str(author.id), - 'book_set-1-id': str(book_ids[1]), - } - formset = FormSet(data=data, instance=author) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for title.']) - self.assertEqual(formset.errors, - [{}, {'__all__': u'Please correct the duplicate values below.'}]) - - FormSet = modelformset_factory(Post, extra=2) - data = { - 'form-TOTAL_FORMS': '2', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - - 'form-0-title': 'blah', - 'form-0-slug': 'Morning', - 'form-0-subtitle': 'foo', - 'form-0-posted': '2009-01-01', - 'form-1-title': 'blah', - 'form-1-slug': 'Morning in Prague', - 'form-1-subtitle': 'rawr', - 'form-1-posted': '2009-01-01' - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for title which must be unique for the date in posted.']) - self.assertEqual(formset.errors, - [{}, {'__all__': u'Please correct the duplicate values below.'}]) - - data = { - 'form-TOTAL_FORMS': '2', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - - 'form-0-title': 'foo', - 'form-0-slug': 'Morning in Prague', - 'form-0-subtitle': 'foo', - 'form-0-posted': '2009-01-01', - 'form-1-title': 'blah', - 'form-1-slug': 'Morning in Prague', - 'form-1-subtitle': 'rawr', - 'form-1-posted': '2009-08-02' - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for slug which must be unique for the year in posted.']) - - data = { - 'form-TOTAL_FORMS': '2', - 'form-INITIAL_FORMS': '0', - 'form-MAX_NUM_FORMS': '', - - 'form-0-title': 'foo', - 'form-0-slug': 'Morning in Prague', - 'form-0-subtitle': 'rawr', - 'form-0-posted': '2008-08-01', - 'form-1-title': 'blah', - 'form-1-slug': 'Prague', - 'form-1-subtitle': 'rawr', - 'form-1-posted': '2009-08-02' - } - formset = FormSet(data) - self.assertFalse(formset.is_valid()) - self.assertEqual(formset._non_form_errors, - [u'Please correct the duplicate data for subtitle which must be unique for the month in posted.']) diff --git a/parts/django/tests/modeltests/model_inheritance/__init__.py b/parts/django/tests/modeltests/model_inheritance/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/model_inheritance/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/model_inheritance/models.py b/parts/django/tests/modeltests/model_inheritance/models.py deleted file mode 100644 index 6cee512..0000000 --- a/parts/django/tests/modeltests/model_inheritance/models.py +++ /dev/null @@ -1,145 +0,0 @@ -""" -XX. Model inheritance - -Model inheritance exists in two varieties: - - abstract base classes which are a way of specifying common - information inherited by the subclasses. They don't exist as a separate - model. - - non-abstract base classes (the default), which are models in their own - right with their own database tables and everything. Their subclasses - have references back to them, created automatically. - -Both styles are demonstrated here. -""" - -from django.db import models - -# -# Abstract base classes -# - -class CommonInfo(models.Model): - name = models.CharField(max_length=50) - age = models.PositiveIntegerField() - - class Meta: - abstract = True - ordering = ['name'] - - def __unicode__(self): - return u'%s %s' % (self.__class__.__name__, self.name) - -class Worker(CommonInfo): - job = models.CharField(max_length=50) - -class Student(CommonInfo): - school_class = models.CharField(max_length=10) - - class Meta: - pass - -class StudentWorker(Student, Worker): - pass - -# -# Abstract base classes with related models -# - -class Post(models.Model): - title = models.CharField(max_length=50) - -class Attachment(models.Model): - post = models.ForeignKey(Post, related_name='attached_%(class)s_set') - content = models.TextField() - - class Meta: - abstract = True - - def __unicode__(self): - return self.content - -class Comment(Attachment): - is_spam = models.BooleanField() - -class Link(Attachment): - url = models.URLField() - -# -# Multi-table inheritance -# - -class Chef(models.Model): - name = models.CharField(max_length=50) - - def __unicode__(self): - return u"%s the chef" % self.name - -class Place(models.Model): - name = models.CharField(max_length=50) - address = models.CharField(max_length=80) - - def __unicode__(self): - return u"%s the place" % self.name - -class Rating(models.Model): - rating = models.IntegerField(null=True, blank=True) - - class Meta: - abstract = True - ordering = ['-rating'] - -class Restaurant(Place, Rating): - serves_hot_dogs = models.BooleanField() - serves_pizza = models.BooleanField() - chef = models.ForeignKey(Chef, null=True, blank=True) - - class Meta(Rating.Meta): - db_table = 'my_restaurant' - - def __unicode__(self): - return u"%s the restaurant" % self.name - -class ItalianRestaurant(Restaurant): - serves_gnocchi = models.BooleanField() - - def __unicode__(self): - return u"%s the italian restaurant" % self.name - -class Supplier(Place): - customers = models.ManyToManyField(Restaurant, related_name='provider') - - def __unicode__(self): - return u"%s the supplier" % self.name - -class ParkingLot(Place): - # An explicit link to the parent (we can control the attribute name). - parent = models.OneToOneField(Place, primary_key=True, parent_link=True) - main_site = models.ForeignKey(Place, related_name='lot') - - def __unicode__(self): - return u"%s the parking lot" % self.name - -# -# Abstract base classes with related models where the sub-class has the -# same name in a different app and inherits from the same abstract base -# class. -# NOTE: The actual API tests for the following classes are in -# model_inheritance_same_model_name/models.py - They are defined -# here in order to have the name conflict between apps -# - -class Title(models.Model): - title = models.CharField(max_length=50) - -class NamedURL(models.Model): - title = models.ForeignKey(Title, related_name='attached_%(app_label)s_%(class)s_set') - url = models.URLField() - - class Meta: - abstract = True - -class Copy(NamedURL): - content = models.TextField() - - def __unicode__(self): - return self.content diff --git a/parts/django/tests/modeltests/model_inheritance/tests.py b/parts/django/tests/modeltests/model_inheritance/tests.py deleted file mode 100644 index 80dd0de..0000000 --- a/parts/django/tests/modeltests/model_inheritance/tests.py +++ /dev/null @@ -1,281 +0,0 @@ -from operator import attrgetter - -from django.conf import settings -from django.core.exceptions import FieldError -from django.db import connection -from django.test import TestCase - -from models import (Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, - Post, Restaurant, Student, StudentWorker, Supplier, Worker) - - -class ModelInheritanceTests(TestCase): - def test_abstract(self): - # The Student and Worker models both have 'name' and 'age' fields on - # them and inherit the __unicode__() method, just as with normal Python - # subclassing. This is useful if you want to factor out common - # information for programming purposes, but still completely - # independent separate models at the database level. - w1 = Worker.objects.create(name="Fred", age=35, job="Quarry worker") - w2 = Worker.objects.create(name="Barney", age=34, job="Quarry worker") - - s = Student.objects.create(name="Pebbles", age=5, school_class="1B") - - self.assertEqual(unicode(w1), "Worker Fred") - self.assertEqual(unicode(s), "Student Pebbles") - - # The children inherit the Meta class of their parents (if they don't - # specify their own). - self.assertQuerysetEqual( - Worker.objects.values("name"), [ - {"name": "Barney"}, - {"name": "Fred"}, - ], - lambda o: o - ) - - # Since Student does not subclass CommonInfo's Meta, it has the effect - # of completely overriding it. So ordering by name doesn't take place - # for Students. - self.assertEqual(Student._meta.ordering, []) - - # However, the CommonInfo class cannot be used as a normal model (it - # doesn't exist as a model). - self.assertRaises(AttributeError, lambda: CommonInfo.objects.all()) - - # A StudentWorker which does not exist is both a Student and Worker - # which does not exist. - self.assertRaises(Student.DoesNotExist, - StudentWorker.objects.get, pk=12321321 - ) - self.assertRaises(Worker.DoesNotExist, - StudentWorker.objects.get, pk=12321321 - ) - - # MultipleObjectsReturned is also inherited. - # This is written out "long form", rather than using __init__/create() - # because of a bug with diamond inheritance (#10808) - sw1 = StudentWorker() - sw1.name = "Wilma" - sw1.age = 35 - sw1.save() - sw2 = StudentWorker() - sw2.name = "Betty" - sw2.age = 24 - sw2.save() - - self.assertRaises(Student.MultipleObjectsReturned, - StudentWorker.objects.get, pk__lt=sw2.pk + 100 - ) - self.assertRaises(Worker.MultipleObjectsReturned, - StudentWorker.objects.get, pk__lt=sw2.pk + 100 - ) - - def test_multiple_table(self): - post = Post.objects.create(title="Lorem Ipsum") - # The Post model has distinct accessors for the Comment and Link models. - post.attached_comment_set.create(content="Save $ on V1agr@", is_spam=True) - post.attached_link_set.create( - content="The Web framework for perfections with deadlines.", - url="http://www.djangoproject.com/" - ) - - # The Post model doesn't have an attribute called - # 'attached_%(class)s_set'. - self.assertRaises(AttributeError, - getattr, post, "attached_%(class)s_set" - ) - - # The Place/Restaurant/ItalianRestaurant models all exist as - # independent models. However, the subclasses also have transparent - # access to the fields of their ancestors. - # Create a couple of Places. - p1 = Place.objects.create(name="Master Shakes", address="666 W. Jersey") - p2 = Place.objects.create(name="Ace Harware", address="1013 N. Ashland") - - # Test constructor for Restaurant. - r = Restaurant.objects.create( - name="Demon Dogs", - address="944 W. Fullerton", - serves_hot_dogs=True, - serves_pizza=False, - rating=2 - ) - # Test the constructor for ItalianRestaurant. - c = Chef.objects.create(name="Albert") - ir = ItalianRestaurant.objects.create( - name="Ristorante Miron", - address="1234 W. Ash", - serves_hot_dogs=False, - serves_pizza=False, - serves_gnocchi=True, - rating=4, - chef=c - ) - self.assertQuerysetEqual( - ItalianRestaurant.objects.filter(address="1234 W. Ash"), [ - "Ristorante Miron", - ], - attrgetter("name") - ) - ir.address = "1234 W. Elm" - ir.save() - self.assertQuerysetEqual( - ItalianRestaurant.objects.filter(address="1234 W. Elm"), [ - "Ristorante Miron", - ], - attrgetter("name") - ) - - # Make sure Restaurant and ItalianRestaurant have the right fields in - # the right order. - self.assertEqual( - [f.name for f in Restaurant._meta.fields], - ["id", "name", "address", "place_ptr", "rating", "serves_hot_dogs", "serves_pizza", "chef"] - ) - self.assertEqual( - [f.name for f in ItalianRestaurant._meta.fields], - ["id", "name", "address", "place_ptr", "rating", "serves_hot_dogs", "serves_pizza", "chef", "restaurant_ptr", "serves_gnocchi"], - ) - self.assertEqual(Restaurant._meta.ordering, ["-rating"]) - - # Even though p.supplier for a Place 'p' (a parent of a Supplier), a - # Restaurant object cannot access that reverse relation, since it's not - # part of the Place-Supplier Hierarchy. - self.assertQuerysetEqual(Place.objects.filter(supplier__name="foo"), []) - self.assertRaises(FieldError, - Restaurant.objects.filter, supplier__name="foo" - ) - - # Parent fields can be used directly in filters on the child model. - self.assertQuerysetEqual( - Restaurant.objects.filter(name="Demon Dogs"), [ - "Demon Dogs", - ], - attrgetter("name") - ) - self.assertQuerysetEqual( - ItalianRestaurant.objects.filter(address="1234 W. Elm"), [ - "Ristorante Miron", - ], - attrgetter("name") - ) - - # Filters against the parent model return objects of the parent's type. - p = Place.objects.get(name="Demon Dogs") - self.assertTrue(type(p) is Place) - - # Since the parent and child are linked by an automatically created - # OneToOneField, you can get from the parent to the child by using the - # child's name. - self.assertEqual( - p.restaurant, Restaurant.objects.get(name="Demon Dogs") - ) - self.assertEqual( - Place.objects.get(name="Ristorante Miron").restaurant.italianrestaurant, - ItalianRestaurant.objects.get(name="Ristorante Miron") - ) - self.assertEqual( - Restaurant.objects.get(name="Ristorante Miron").italianrestaurant, - ItalianRestaurant.objects.get(name="Ristorante Miron") - ) - - # This won't work because the Demon Dogs restaurant is not an Italian - # restaurant. - self.assertRaises(ItalianRestaurant.DoesNotExist, - lambda: p.restaurant.italianrestaurant - ) - # An ItalianRestaurant which does not exist is also a Place which does - # not exist. - self.assertRaises(Place.DoesNotExist, - ItalianRestaurant.objects.get, name="The Noodle Void" - ) - # MultipleObjectsReturned is also inherited. - self.assertRaises(Place.MultipleObjectsReturned, - Restaurant.objects.get, id__lt=12321 - ) - - # Related objects work just as they normally do. - s1 = Supplier.objects.create(name="Joe's Chickens", address="123 Sesame St") - s1.customers = [r, ir] - s2 = Supplier.objects.create(name="Luigi's Pasta", address="456 Sesame St") - s2.customers = [ir] - - # This won't work because the Place we select is not a Restaurant (it's - # a Supplier). - p = Place.objects.get(name="Joe's Chickens") - self.assertRaises(Restaurant.DoesNotExist, - lambda: p.restaurant - ) - - self.assertEqual(p.supplier, s1) - self.assertQuerysetEqual( - ir.provider.order_by("-name"), [ - "Luigi's Pasta", - "Joe's Chickens" - ], - attrgetter("name") - ) - self.assertQuerysetEqual( - Restaurant.objects.filter(provider__name__contains="Chickens"), [ - "Ristorante Miron", - "Demon Dogs", - ], - attrgetter("name") - ) - self.assertQuerysetEqual( - ItalianRestaurant.objects.filter(provider__name__contains="Chickens"), [ - "Ristorante Miron", - ], - attrgetter("name"), - ) - - park1 = ParkingLot.objects.create( - name="Main St", address="111 Main St", main_site=s1 - ) - park2 = ParkingLot.objects.create( - name="Well Lit", address="124 Sesame St", main_site=ir - ) - - self.assertEqual( - Restaurant.objects.get(lot__name="Well Lit").name, - "Ristorante Miron" - ) - - # The update() command can update fields in parent and child classes at - # once (although it executed multiple SQL queries to do so). - rows = Restaurant.objects.filter( - serves_hot_dogs=True, name__contains="D" - ).update( - name="Demon Puppies", serves_hot_dogs=False - ) - self.assertEqual(rows, 1) - - r1 = Restaurant.objects.get(pk=r.pk) - self.assertFalse(r1.serves_hot_dogs) - self.assertEqual(r1.name, "Demon Puppies") - - # The values() command also works on fields from parent models. - self.assertQuerysetEqual( - ItalianRestaurant.objects.values("name", "rating"), [ - {"rating": 4, "name": "Ristorante Miron"} - ], - lambda o: o - ) - - # select_related works with fields from the parent object as if they - # were a normal part of the model. - old_DEBUG = settings.DEBUG - try: - settings.DEBUG = True - starting_queries = len(connection.queries) - ItalianRestaurant.objects.all()[0].chef - self.assertEqual(len(connection.queries) - starting_queries, 2) - - starting_queries = len(connection.queries) - ItalianRestaurant.objects.select_related("chef")[0].chef - self.assertEqual(len(connection.queries) - starting_queries, 1) - finally: - settings.DEBUG = old_DEBUG - - diff --git a/parts/django/tests/modeltests/model_inheritance_same_model_name/__init__.py b/parts/django/tests/modeltests/model_inheritance_same_model_name/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/model_inheritance_same_model_name/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/model_inheritance_same_model_name/models.py b/parts/django/tests/modeltests/model_inheritance_same_model_name/models.py deleted file mode 100644 index 40de027..0000000 --- a/parts/django/tests/modeltests/model_inheritance_same_model_name/models.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -XX. Model inheritance - -Model inheritance across apps can result in models with the same name resulting -in the need for an %(app_label)s format string. This app specifically tests -this feature by redefining the Copy model from model_inheritance/models.py -""" - -from django.db import models -from modeltests.model_inheritance.models import NamedURL - -# -# Abstract base classes with related models -# -class Copy(NamedURL): - content = models.TextField() - - def __unicode__(self): - return self.content diff --git a/parts/django/tests/modeltests/model_inheritance_same_model_name/tests.py b/parts/django/tests/modeltests/model_inheritance_same_model_name/tests.py deleted file mode 100644 index 3f1e345..0000000 --- a/parts/django/tests/modeltests/model_inheritance_same_model_name/tests.py +++ /dev/null @@ -1,32 +0,0 @@ -from django.test import TestCase -from modeltests.model_inheritance.models import Title - -class InheritanceSameModelNameTests(TestCase): - - def setUp(self): - # The Title model has distinct accessors for both - # model_inheritance.Copy and model_inheritance_same_model_name.Copy - # models. - self.title = Title.objects.create(title='Lorem Ipsum') - - def test_inheritance_related_name(self): - from modeltests.model_inheritance.models import Copy - self.assertEquals( - self.title.attached_model_inheritance_copy_set.create( - content='Save $ on V1agr@', - url='http://v1agra.com/', - title='V1agra is spam', - ), Copy.objects.get(content='Save $ on V1agr@')) - - def test_inheritance_with_same_model_name(self): - from modeltests.model_inheritance_same_model_name.models import Copy - self.assertEquals( - self.title.attached_model_inheritance_same_model_name_copy_set.create( - content='The Web framework for perfectionists with deadlines.', - url='http://www.djangoproject.com/', - title='Django Rocks' - ), Copy.objects.get(content='The Web framework for perfectionists with deadlines.')) - - def test_related_name_attribute_exists(self): - # The Post model doesn't have an attribute called 'attached_%(app_label)s_%(class)s_set'. - self.assertEqual(hasattr(self.title, 'attached_%(app_label)s_%(class)s_set'), False) diff --git a/parts/django/tests/modeltests/model_package/__init__.py b/parts/django/tests/modeltests/model_package/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/parts/django/tests/modeltests/model_package/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/parts/django/tests/modeltests/model_package/models/__init__.py b/parts/django/tests/modeltests/model_package/models/__init__.py deleted file mode 100644 index 91e1b02..0000000 --- a/parts/django/tests/modeltests/model_package/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Import all the models from subpackages -from article import Article -from publication import Publication diff --git a/parts/django/tests/modeltests/model_package/models/article.py b/parts/django/tests/modeltests/model_package/models/article.py deleted file mode 100644 index c8fae1c..0000000 --- a/parts/django/tests/modeltests/model_package/models/article.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.db import models -from django.contrib.sites.models import Site - -class Article(models.Model): - sites = models.ManyToManyField(Site) - headline = models.CharField(max_length=100) - publications = models.ManyToManyField("model_package.Publication", null=True, blank=True,) - - class Meta: - app_label = 'model_package' diff --git a/parts/django/tests/modeltests/model_package/models/publication.py b/parts/django/tests/modeltests/model_package/models/publication.py deleted file mode 100644 index 4dc2d6a..0000000 --- a/parts/django/tests/modeltests/model_package/models/publication.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.db import models - -class Publication(models.Model): - title = models.CharField(max_length=30) - - class Meta: - app_label = 'model_package' diff --git a/parts/django/tests/modeltests/model_package/tests.py b/parts/django/tests/modeltests/model_package/tests.py deleted file mode 100644 index e63e2e6..0000000 --- a/parts/django/tests/modeltests/model_package/tests.py +++ /dev/null @@ -1,72 +0,0 @@ -from django.contrib.sites.models import Site -from django.db import models -from django.test import TestCase - -from models.publication import Publication -from models.article import Article - - -class Advertisment(models.Model): - customer = models.CharField(max_length=100) - publications = models.ManyToManyField( - "model_package.Publication", null=True, blank=True - ) - - class Meta: - app_label = 'model_package' - - -class ModelPackageTests(TestCase): - def test_model_packages(self): - p = Publication.objects.create(title="FooBar") - - current_site = Site.objects.get_current() - self.assertEqual(current_site.domain, "example.com") - - # Regression for #12168: models split into subpackages still get M2M - # tables - a = Article.objects.create(headline="a foo headline") - a.publications.add(p) - a.sites.add(current_site) - - a = Article.objects.get(id=a.pk) - self.assertEqual(a.id, a.pk) - self.assertEqual(a.sites.count(), 1) - - # Regression for #12245 - Models can exist in the test package, too - ad = Advertisment.objects.create(customer="Lawrence Journal-World") - ad.publications.add(p) - - ad = Advertisment.objects.get(id=ad.pk) - self.assertEqual(ad.publications.count(), 1) - - # Regression for #12386 - field names on the autogenerated intermediate - # class that are specified as dotted strings don't retain any path - # component for the field or column name - self.assertEqual( - Article.publications.through._meta.fields[1].name, 'article' - ) - self.assertEqual( - Article.publications.through._meta.fields[1].get_attname_column(), - ('article_id', 'article_id') - ) - self.assertEqual( - Article.publications.through._meta.fields[2].name, 'publication' - ) - self.assertEqual( - Article.publications.through._meta.fields[2].get_attname_column(), - ('publication_id', 'publication_id') - ) - - # The oracle backend truncates the name to 'model_package_article_publ233f'. - self.assertTrue( - Article._meta.get_field('publications').m2m_db_table() in ('model_package_article_publications', 'model_package_article_publ233f') - ) - - self.assertEqual( - Article._meta.get_field('publications').m2m_column_name(), 'article_id' - ) - self.assertEqual( - Article._meta.get_field('publications').m2m_reverse_name(), - 'publication_id' - ) diff --git a/parts/django/tests/modeltests/mutually_referential/__init__.py b/parts/django/tests/modeltests/mutually_referential/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/mutually_referential/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/mutually_referential/models.py b/parts/django/tests/modeltests/mutually_referential/models.py deleted file mode 100644 index db05cbc..0000000 --- a/parts/django/tests/modeltests/mutually_referential/models.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -24. Mutually referential many-to-one relationships - -Strings can be used instead of model literals to set up "lazy" relations. -""" - -from django.db.models import * - -class Parent(Model): - name = CharField(max_length=100) - - # Use a simple string for forward declarations. - bestchild = ForeignKey("Child", null=True, related_name="favoured_by") - -class Child(Model): - name = CharField(max_length=100) - - # You can also explicitally specify the related app. - parent = ForeignKey("mutually_referential.Parent") diff --git a/parts/django/tests/modeltests/mutually_referential/tests.py b/parts/django/tests/modeltests/mutually_referential/tests.py deleted file mode 100644 index 101d67c..0000000 --- a/parts/django/tests/modeltests/mutually_referential/tests.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.test import TestCase -from models import Parent, Child - -class MutuallyReferentialTests(TestCase): - - def test_mutually_referential(self): - # Create a Parent - q = Parent(name='Elizabeth') - q.save() - - # Create some children - c = q.child_set.create(name='Charles') - e = q.child_set.create(name='Edward') - - # Set the best child - # No assertion require here; if basic assignment and - # deletion works, the test passes. - q.bestchild = c - q.save() - q.delete() diff --git a/parts/django/tests/modeltests/one_to_one/__init__.py b/parts/django/tests/modeltests/one_to_one/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/one_to_one/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/one_to_one/models.py b/parts/django/tests/modeltests/one_to_one/models.py deleted file mode 100644 index f263735..0000000 --- a/parts/django/tests/modeltests/one_to_one/models.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -10. One-to-one relationships - -To define a one-to-one relationship, use ``OneToOneField()``. - -In this example, a ``Place`` optionally can be a ``Restaurant``. -""" - -from django.db import models, transaction, IntegrityError - -class Place(models.Model): - name = models.CharField(max_length=50) - address = models.CharField(max_length=80) - - def __unicode__(self): - return u"%s the place" % self.name - -class Restaurant(models.Model): - place = models.OneToOneField(Place, primary_key=True) - serves_hot_dogs = models.BooleanField() - serves_pizza = models.BooleanField() - - def __unicode__(self): - return u"%s the restaurant" % self.place.name - -class Waiter(models.Model): - restaurant = models.ForeignKey(Restaurant) - name = models.CharField(max_length=50) - - def __unicode__(self): - return u"%s the waiter at %s" % (self.name, self.restaurant) - -class ManualPrimaryKey(models.Model): - primary_key = models.CharField(max_length=10, primary_key=True) - name = models.CharField(max_length = 50) - -class RelatedModel(models.Model): - link = models.OneToOneField(ManualPrimaryKey) - name = models.CharField(max_length = 50) - -class MultiModel(models.Model): - link1 = models.OneToOneField(Place) - link2 = models.OneToOneField(ManualPrimaryKey) - name = models.CharField(max_length=50) - - def __unicode__(self): - return u"Multimodel %s" % self.name diff --git a/parts/django/tests/modeltests/one_to_one/tests.py b/parts/django/tests/modeltests/one_to_one/tests.py deleted file mode 100644 index c3e1704..0000000 --- a/parts/django/tests/modeltests/one_to_one/tests.py +++ /dev/null @@ -1,119 +0,0 @@ -from django.test import TestCase -from django.db import transaction, IntegrityError -from models import Place, Restaurant, Waiter, ManualPrimaryKey, RelatedModel, MultiModel - -class OneToOneTests(TestCase): - - def setUp(self): - self.p1 = Place(name='Demon Dogs', address='944 W. Fullerton') - self.p1.save() - self.p2 = Place(name='Ace Hardware', address='1013 N. Ashland') - self.p2.save() - self.r = Restaurant(place=self.p1, serves_hot_dogs=True, serves_pizza=False) - self.r.save() - - def test_getter(self): - # A Restaurant can access its place. - self.assertEqual(repr(self.r.place), '<Place: Demon Dogs the place>') - # A Place can access its restaurant, if available. - self.assertEqual(repr(self.p1.restaurant), '<Restaurant: Demon Dogs the restaurant>') - # p2 doesn't have an associated restaurant. - self.assertRaises(Restaurant.DoesNotExist, getattr, self.p2, 'restaurant') - - def test_setter(self): - # Set the place using assignment notation. Because place is the primary - # key on Restaurant, the save will create a new restaurant - self.r.place = self.p2 - self.r.save() - self.assertEqual(repr(self.p2.restaurant), '<Restaurant: Ace Hardware the restaurant>') - self.assertEqual(repr(self.r.place), '<Place: Ace Hardware the place>') - self.assertEqual(self.p2.pk, self.r.pk) - # Set the place back again, using assignment in the reverse direction. - self.p1.restaurant = self.r - self.assertEqual(repr(self.p1.restaurant), '<Restaurant: Demon Dogs the restaurant>') - r = Restaurant.objects.get(pk=self.p1.id) - self.assertEqual(repr(r.place), '<Place: Demon Dogs the place>') - - def test_manager_all(self): - # Restaurant.objects.all() just returns the Restaurants, not the Places. - self.assertQuerysetEqual(Restaurant.objects.all(), [ - '<Restaurant: Demon Dogs the restaurant>', - ]) - # Place.objects.all() returns all Places, regardless of whether they - # have Restaurants. - self.assertQuerysetEqual(Place.objects.order_by('name'), [ - '<Place: Ace Hardware the place>', - '<Place: Demon Dogs the place>', - ]) - - def test_manager_get(self): - def assert_get_restaurant(**params): - self.assertEqual(repr(Restaurant.objects.get(**params)), - '<Restaurant: Demon Dogs the restaurant>') - assert_get_restaurant(place__id__exact=self.p1.pk) - assert_get_restaurant(place__id=self.p1.pk) - assert_get_restaurant(place__exact=self.p1.pk) - assert_get_restaurant(place__exact=self.p1) - assert_get_restaurant(place=self.p1.pk) - assert_get_restaurant(place=self.p1) - assert_get_restaurant(pk=self.p1.pk) - assert_get_restaurant(place__pk__exact=self.p1.pk) - assert_get_restaurant(place__pk=self.p1.pk) - assert_get_restaurant(place__name__startswith="Demon") - - def assert_get_place(**params): - self.assertEqual(repr(Place.objects.get(**params)), - '<Place: Demon Dogs the place>') - assert_get_place(restaurant__place__exact=self.p1.pk) - assert_get_place(restaurant__place__exact=self.p1) - assert_get_place(restaurant__place__pk=self.p1.pk) - assert_get_place(restaurant__exact=self.p1.pk) - assert_get_place(restaurant__exact=self.r) - assert_get_place(restaurant__pk=self.p1.pk) - assert_get_place(restaurant=self.p1.pk) - assert_get_place(restaurant=self.r) - assert_get_place(id__exact=self.p1.pk) - assert_get_place(pk=self.p1.pk) - - def test_foreign_key(self): - # Add a Waiter to the Restaurant. - w = self.r.waiter_set.create(name='Joe') - w.save() - self.assertEqual(repr(w), '<Waiter: Joe the waiter at Demon Dogs the restaurant>') - # Query the waiters - def assert_filter_waiters(**params): - self.assertQuerysetEqual(Waiter.objects.filter(**params), [ - '<Waiter: Joe the waiter at Demon Dogs the restaurant>' - ]) - assert_filter_waiters(restaurant__place__exact=self.p1.pk) - assert_filter_waiters(restaurant__place__exact=self.p1) - assert_filter_waiters(restaurant__place__pk=self.p1.pk) - assert_filter_waiters(restaurant__exact=self.p1.pk) - assert_filter_waiters(restaurant__exact=self.p1) - assert_filter_waiters(restaurant__pk=self.p1.pk) - assert_filter_waiters(restaurant=self.p1.pk) - assert_filter_waiters(restaurant=self.r) - assert_filter_waiters(id__exact=self.p1.pk) - assert_filter_waiters(pk=self.p1.pk) - # Delete the restaurant; the waiter should also be removed - r = Restaurant.objects.get(pk=self.p1.pk) - r.delete() - self.assertEqual(Waiter.objects.count(), 0) - - def test_multiple_o2o(self): - # One-to-one fields still work if you create your own primary key - o1 = ManualPrimaryKey(primary_key="abc123", name="primary") - o1.save() - o2 = RelatedModel(link=o1, name="secondary") - o2.save() - - # You can have multiple one-to-one fields on a model, too. - x1 = MultiModel(link1=self.p1, link2=o1, name="x1") - x1.save() - self.assertEqual(repr(o1.multimodel), '<MultiModel: Multimodel x1>') - # This will fail because each one-to-one field must be unique (and - # link2=o1 was used for x1, above). - sid = transaction.savepoint() - mm = MultiModel(link1=self.p2, link2=o1, name="x1") - self.assertRaises(IntegrityError, mm.save) - transaction.savepoint_rollback(sid) diff --git a/parts/django/tests/modeltests/or_lookups/__init__.py b/parts/django/tests/modeltests/or_lookups/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/or_lookups/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/or_lookups/models.py b/parts/django/tests/modeltests/or_lookups/models.py deleted file mode 100644 index 7f14ba5..0000000 --- a/parts/django/tests/modeltests/or_lookups/models.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -19. OR lookups - -To perform an OR lookup, or a lookup that combines ANDs and ORs, combine -``QuerySet`` objects using ``&`` and ``|`` operators. - -Alternatively, use positional arguments, and pass one or more expressions of -clauses using the variable ``django.db.models.Q`` (or any object with an -``add_to_query`` method). -""" - -from django.db import models - -class Article(models.Model): - headline = models.CharField(max_length=50) - pub_date = models.DateTimeField() - - class Meta: - ordering = ('pub_date',) - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/or_lookups/tests.py b/parts/django/tests/modeltests/or_lookups/tests.py deleted file mode 100644 index ad218cd..0000000 --- a/parts/django/tests/modeltests/or_lookups/tests.py +++ /dev/null @@ -1,232 +0,0 @@ -from datetime import datetime -from operator import attrgetter - -from django.db.models import Q -from django.test import TestCase - -from models import Article - - -class OrLookupsTests(TestCase): - - def setUp(self): - self.a1 = Article.objects.create( - headline='Hello', pub_date=datetime(2005, 11, 27) - ).pk - self.a2 = Article.objects.create( - headline='Goodbye', pub_date=datetime(2005, 11, 28) - ).pk - self.a3 = Article.objects.create( - headline='Hello and goodbye', pub_date=datetime(2005, 11, 29) - ).pk - - def test_filter_or(self): - self.assertQuerysetEqual( - Article.objects.filter(headline__startswith='Hello') | Article.objects.filter(headline__startswith='Goodbye'), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - self.assertQuerysetEqual( - Article.objects.filter(headline__contains='Hello') | Article.objects.filter(headline__contains='bye'), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - self.assertQuerysetEqual( - Article.objects.filter(headline__iexact='Hello') | Article.objects.filter(headline__contains='ood'), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - self.assertQuerysetEqual( - Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__startswith='Goodbye')), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - - def test_stages(self): - # You can shorten this syntax with code like the following, which is - # especially useful if building the query in stages: - articles = Article.objects.all() - self.assertQuerysetEqual( - articles.filter(headline__startswith='Hello') & articles.filter(headline__startswith='Goodbye'), - [] - ) - self.assertQuerysetEqual( - articles.filter(headline__startswith='Hello') & articles.filter(headline__contains='bye'), [ - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - def test_pk_q(self): - self.assertQuerysetEqual( - Article.objects.filter(Q(pk=self.a1) | Q(pk=self.a2)), [ - 'Hello', - 'Goodbye' - ], - attrgetter("headline") - ) - - self.assertQuerysetEqual( - Article.objects.filter(Q(pk=self.a1) | Q(pk=self.a2) | Q(pk=self.a3)), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - def test_pk_in(self): - self.assertQuerysetEqual( - Article.objects.filter(pk__in=[self.a1, self.a2, self.a3]), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - self.assertQuerysetEqual( - Article.objects.filter(pk__in=(self.a1, self.a2, self.a3)), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - self.assertQuerysetEqual( - Article.objects.filter(pk__in=[self.a1, self.a2, self.a3, 40000]), [ - 'Hello', - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - def test_q_negated(self): - # Q objects can be negated - self.assertQuerysetEqual( - Article.objects.filter(Q(pk=self.a1) | ~Q(pk=self.a2)), [ - 'Hello', - 'Hello and goodbye' - ], - attrgetter("headline") - ) - - self.assertQuerysetEqual( - Article.objects.filter(~Q(pk=self.a1) & ~Q(pk=self.a2)), [ - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - # This allows for more complex queries than filter() and exclude() - # alone would allow - self.assertQuerysetEqual( - Article.objects.filter(Q(pk=self.a1) & (~Q(pk=self.a2) | Q(pk=self.a3))), [ - 'Hello' - ], - attrgetter("headline"), - ) - - def test_complex_filter(self): - # The 'complex_filter' method supports framework features such as - # 'limit_choices_to' which normally take a single dictionary of lookup - # arguments but need to support arbitrary queries via Q objects too. - self.assertQuerysetEqual( - Article.objects.complex_filter({'pk': self.a1}), [ - 'Hello' - ], - attrgetter("headline"), - ) - - self.assertQuerysetEqual( - Article.objects.complex_filter(Q(pk=self.a1) | Q(pk=self.a2)), [ - 'Hello', - 'Goodbye' - ], - attrgetter("headline"), - ) - - def test_empty_in(self): - # Passing "in" an empty list returns no results ... - self.assertQuerysetEqual( - Article.objects.filter(pk__in=[]), - [] - ) - # ... but can return results if we OR it with another query. - self.assertQuerysetEqual( - Article.objects.filter(Q(pk__in=[]) | Q(headline__icontains='goodbye')), [ - 'Goodbye', - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - def test_q_and(self): - # Q arg objects are ANDed - self.assertQuerysetEqual( - Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye')), [ - 'Hello and goodbye' - ], - attrgetter("headline") - ) - # Q arg AND order is irrelevant - self.assertQuerysetEqual( - Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello'), [ - 'Hello and goodbye' - ], - attrgetter("headline"), - ) - - self.assertQuerysetEqual( - Article.objects.filter(Q(headline__startswith='Hello') & Q(headline__startswith='Goodbye')), - [] - ) - - def test_q_exclude(self): - self.assertQuerysetEqual( - Article.objects.exclude(Q(headline__startswith='Hello')), [ - 'Goodbye' - ], - attrgetter("headline") - ) - - def test_other_arg_queries(self): - # Try some arg queries with operations other than filter. - self.assertEqual( - Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye')).headline, - 'Hello and goodbye' - ) - - self.assertEqual( - Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__contains='bye')).count(), - 3 - ) - - self.assertQuerysetEqual( - Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye')).values(), [ - {"headline": "Hello and goodbye", "id": self.a3, "pub_date": datetime(2005, 11, 29)}, - ], - lambda o: o, - ) - - self.assertEqual( - Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([self.a1, self.a2]), - {self.a1: Article.objects.get(pk=self.a1)} - ) diff --git a/parts/django/tests/modeltests/order_with_respect_to/__init__.py b/parts/django/tests/modeltests/order_with_respect_to/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/order_with_respect_to/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/order_with_respect_to/models.py b/parts/django/tests/modeltests/order_with_respect_to/models.py deleted file mode 100644 index 59f01d4..0000000 --- a/parts/django/tests/modeltests/order_with_respect_to/models.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Tests for the order_with_respect_to Meta attribute. -""" - -from django.db import models - - -class Question(models.Model): - text = models.CharField(max_length=200) - -class Answer(models.Model): - text = models.CharField(max_length=200) - question = models.ForeignKey(Question) - - class Meta: - order_with_respect_to = 'question' - - def __unicode__(self): - return unicode(self.text) - -class Post(models.Model): - title = models.CharField(max_length=200) - parent = models.ForeignKey("self", related_name="children", null=True) - - class Meta: - order_with_respect_to = "parent" - - def __unicode__(self): - return self.title diff --git a/parts/django/tests/modeltests/order_with_respect_to/tests.py b/parts/django/tests/modeltests/order_with_respect_to/tests.py deleted file mode 100644 index 328d968..0000000 --- a/parts/django/tests/modeltests/order_with_respect_to/tests.py +++ /dev/null @@ -1,71 +0,0 @@ -from operator import attrgetter - -from django.test import TestCase - -from models import Post, Question, Answer - - -class OrderWithRespectToTests(TestCase): - def test_basic(self): - q1 = Question.objects.create(text="Which Beatle starts with the letter 'R'?") - q2 = Question.objects.create(text="What is your name?") - - Answer.objects.create(text="John", question=q1) - Answer.objects.create(text="Jonno", question=q2) - Answer.objects.create(text="Paul", question=q1) - Answer.objects.create(text="Paulo", question=q2) - Answer.objects.create(text="George", question=q1) - Answer.objects.create(text="Ringo", question=q1) - - # The answers will always be ordered in the order they were inserted. - self.assertQuerysetEqual( - q1.answer_set.all(), [ - "John", "Paul", "George", "Ringo", - ], - attrgetter("text"), - ) - - # We can retrieve the answers related to a particular object, in the - # order they were created, once we have a particular object. - a1 = Answer.objects.filter(question=q1)[0] - self.assertEqual(a1.text, "John") - a2 = a1.get_next_in_order() - self.assertEqual(a2.text, "Paul") - a4 = list(Answer.objects.filter(question=q1))[-1] - self.assertEqual(a4.text, "Ringo") - self.assertEqual(a4.get_previous_in_order().text, "George") - - # Determining (and setting) the ordering for a particular item is also - # possible. - id_list = [o.pk for o in q1.answer_set.all()] - self.assertEqual(a2.question.get_answer_order(), id_list) - - a5 = Answer.objects.create(text="Number five", question=q1) - - # It doesn't matter which answer we use to check the order, it will - # always be the same. - self.assertEqual( - a2.question.get_answer_order(), a5.question.get_answer_order() - ) - - # The ordering can be altered: - id_list = [o.pk for o in q1.answer_set.all()] - x = id_list.pop() - id_list.insert(-1, x) - self.assertNotEqual(a5.question.get_answer_order(), id_list) - a5.question.set_answer_order(id_list) - self.assertQuerysetEqual( - q1.answer_set.all(), [ - "John", "Paul", "George", "Number five", "Ringo" - ], - attrgetter("text") - ) - - def test_recursive_ordering(self): - p1 = Post.objects.create(title='1') - p2 = Post.objects.create(title='2') - p1_1 = Post.objects.create(title="1.1", parent=p1) - p1_2 = Post.objects.create(title="1.2", parent=p1) - p2_1 = Post.objects.create(title="2.1", parent=p2) - p1_3 = Post.objects.create(title="1.3", parent=p1) - self.assertEqual(p1.get_post_order(), [p1_1.pk, p1_2.pk, p1_3.pk]) diff --git a/parts/django/tests/modeltests/ordering/__init__.py b/parts/django/tests/modeltests/ordering/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/ordering/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/ordering/models.py b/parts/django/tests/modeltests/ordering/models.py deleted file mode 100644 index 25d3c2c..0000000 --- a/parts/django/tests/modeltests/ordering/models.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -6. Specifying ordering - -Specify default ordering for a model using the ``ordering`` attribute, which -should be a list or tuple of field names. This tells Django how to order -``QuerySet`` results. - -If a field name in ``ordering`` starts with a hyphen, that field will be -ordered in descending order. Otherwise, it'll be ordered in ascending order. -The special-case field name ``"?"`` specifies random order. - -The ordering attribute is not required. If you leave it off, ordering will be -undefined -- not random, just undefined. -""" - -from django.db import models - - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateTimeField() - class Meta: - ordering = ('-pub_date', 'headline') - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/ordering/tests.py b/parts/django/tests/modeltests/ordering/tests.py deleted file mode 100644 index 77862c5..0000000 --- a/parts/django/tests/modeltests/ordering/tests.py +++ /dev/null @@ -1,137 +0,0 @@ -from datetime import datetime -from operator import attrgetter - -from django.test import TestCase - -from models import Article - - -class OrderingTests(TestCase): - def test_basic(self): - a1 = Article.objects.create( - headline="Article 1", pub_date=datetime(2005, 7, 26) - ) - a2 = Article.objects.create( - headline="Article 2", pub_date=datetime(2005, 7, 27) - ) - a3 = Article.objects.create( - headline="Article 3", pub_date=datetime(2005, 7, 27) - ) - a4 = Article.objects.create( - headline="Article 4", pub_date=datetime(2005, 7, 28) - ) - - # By default, Article.objects.all() orders by pub_date descending, then - # headline ascending. - self.assertQuerysetEqual( - Article.objects.all(), [ - "Article 4", - "Article 2", - "Article 3", - "Article 1", - ], - attrgetter("headline") - ) - - # Override ordering with order_by, which is in the same format as the - # ordering attribute in models. - self.assertQuerysetEqual( - Article.objects.order_by("headline"), [ - "Article 1", - "Article 2", - "Article 3", - "Article 4", - ], - attrgetter("headline") - ) - self.assertQuerysetEqual( - Article.objects.order_by("pub_date", "-headline"), [ - "Article 1", - "Article 3", - "Article 2", - "Article 4", - ], - attrgetter("headline") - ) - - # Only the last order_by has any effect (since they each override any - # previous ordering). - self.assertQuerysetEqual( - Article.objects.order_by("id"), [ - "Article 1", - "Article 2", - "Article 3", - "Article 4", - ], - attrgetter("headline") - ) - self.assertQuerysetEqual( - Article.objects.order_by("id").order_by("-headline"), [ - "Article 4", - "Article 3", - "Article 2", - "Article 1", - ], - attrgetter("headline") - ) - - # Use the 'stop' part of slicing notation to limit the results. - self.assertQuerysetEqual( - Article.objects.order_by("headline")[:2], [ - "Article 1", - "Article 2", - ], - attrgetter("headline") - ) - - # Use the 'stop' and 'start' parts of slicing notation to offset the - # result list. - self.assertQuerysetEqual( - Article.objects.order_by("headline")[1:3], [ - "Article 2", - "Article 3", - ], - attrgetter("headline") - ) - - # Getting a single item should work too: - self.assertEqual(Article.objects.all()[0], a4) - - # Use '?' to order randomly. - self.assertEqual( - len(list(Article.objects.order_by("?"))), 4 - ) - - # Ordering can be reversed using the reverse() method on a queryset. - # This allows you to extract things like "the last two items" (reverse - # and then take the first two). - self.assertQuerysetEqual( - Article.objects.all().reverse()[:2], [ - "Article 1", - "Article 3", - ], - attrgetter("headline") - ) - - # Ordering can be based on fields included from an 'extra' clause - self.assertQuerysetEqual( - Article.objects.extra(select={"foo": "pub_date"}, order_by=["foo", "headline"]), [ - "Article 1", - "Article 2", - "Article 3", - "Article 4", - ], - attrgetter("headline") - ) - - # If the extra clause uses an SQL keyword for a name, it will be - # protected by quoting. - self.assertQuerysetEqual( - Article.objects.extra(select={"order": "pub_date"}, order_by=["order", "headline"]), [ - "Article 1", - "Article 2", - "Article 3", - "Article 4", - ], - attrgetter("headline") - ) diff --git a/parts/django/tests/modeltests/pagination/__init__.py b/parts/django/tests/modeltests/pagination/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/pagination/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/pagination/models.py b/parts/django/tests/modeltests/pagination/models.py deleted file mode 100644 index 48484dd..0000000 --- a/parts/django/tests/modeltests/pagination/models.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -30. Object pagination - -Django provides a framework for paginating a list of objects in a few lines -of code. This is often useful for dividing search results or long lists of -objects into easily readable pages. -""" - -from django.db import models - - -class Article(models.Model): - headline = models.CharField(max_length=100, default='Default headline') - pub_date = models.DateTimeField() - - def __unicode__(self): - return self.headline diff --git a/parts/django/tests/modeltests/pagination/tests.py b/parts/django/tests/modeltests/pagination/tests.py deleted file mode 100644 index eaee466..0000000 --- a/parts/django/tests/modeltests/pagination/tests.py +++ /dev/null @@ -1,132 +0,0 @@ -from datetime import datetime -from operator import attrgetter - -from django.core.paginator import Paginator, InvalidPage, EmptyPage -from django.test import TestCase - -from models import Article - - -class CountContainer(object): - def count(self): - return 42 - -class LenContainer(object): - def __len__(self): - return 42 - -class PaginationTests(TestCase): - def setUp(self): - # Prepare a list of objects for pagination. - for x in range(1, 10): - a = Article(headline='Article %s' % x, pub_date=datetime(2005, 7, 29)) - a.save() - - def test_paginator(self): - paginator = Paginator(Article.objects.all(), 5) - self.assertEqual(9, paginator.count) - self.assertEqual(2, paginator.num_pages) - self.assertEqual([1, 2], paginator.page_range) - - def test_first_page(self): - paginator = Paginator(Article.objects.all(), 5) - p = paginator.page(1) - self.assertEqual(u"<Page 1 of 2>", unicode(p)) - self.assertQuerysetEqual(p.object_list, [ - "<Article: Article 1>", - "<Article: Article 2>", - "<Article: Article 3>", - "<Article: Article 4>", - "<Article: Article 5>" - ] - ) - self.assertTrue(p.has_next()) - self.assertFalse(p.has_previous()) - self.assertTrue(p.has_other_pages()) - self.assertEqual(2, p.next_page_number()) - self.assertEqual(0, p.previous_page_number()) - self.assertEqual(1, p.start_index()) - self.assertEqual(5, p.end_index()) - - def test_last_page(self): - paginator = Paginator(Article.objects.all(), 5) - p = paginator.page(2) - self.assertEqual(u"<Page 2 of 2>", unicode(p)) - self.assertQuerysetEqual(p.object_list, [ - "<Article: Article 6>", - "<Article: Article 7>", - "<Article: Article 8>", - "<Article: Article 9>" - ] - ) - self.assertFalse(p.has_next()) - self.assertTrue(p.has_previous()) - self.assertTrue(p.has_other_pages()) - self.assertEqual(3, p.next_page_number()) - self.assertEqual(1, p.previous_page_number()) - self.assertEqual(6, p.start_index()) - self.assertEqual(9, p.end_index()) - - def test_empty_page(self): - paginator = Paginator(Article.objects.all(), 5) - self.assertRaises(EmptyPage, paginator.page, 0) - self.assertRaises(EmptyPage, paginator.page, 3) - - # Empty paginators with allow_empty_first_page=True. - paginator = Paginator(Article.objects.filter(id=0), 5, allow_empty_first_page=True) - self.assertEqual(0, paginator.count) - self.assertEqual(1, paginator.num_pages) - self.assertEqual([1], paginator.page_range) - - # Empty paginators with allow_empty_first_page=False. - paginator = Paginator(Article.objects.filter(id=0), 5, allow_empty_first_page=False) - self.assertEqual(0, paginator.count) - self.assertEqual(0, paginator.num_pages) - self.assertEqual([], paginator.page_range) - - def test_invalid_page(self): - paginator = Paginator(Article.objects.all(), 5) - self.assertRaises(InvalidPage, paginator.page, 7) - - def test_orphans(self): - # Add a few more records to test out the orphans feature. - for x in range(10, 13): - Article(headline="Article %s" % x, pub_date=datetime(2006, 10, 6)).save() - - # With orphans set to 3 and 10 items per page, we should get all 12 items on a single page. - paginator = Paginator(Article.objects.all(), 10, orphans=3) - self.assertEqual(1, paginator.num_pages) - - # With orphans only set to 1, we should get two pages. - paginator = Paginator(Article.objects.all(), 10, orphans=1) - self.assertEqual(2, paginator.num_pages) - - def test_paginate_list(self): - # Paginators work with regular lists/tuples, too -- not just with QuerySets. - paginator = Paginator([1, 2, 3, 4, 5, 6, 7, 8, 9], 5) - self.assertEqual(9, paginator.count) - self.assertEqual(2, paginator.num_pages) - self.assertEqual([1, 2], paginator.page_range) - p = paginator.page(1) - self.assertEqual(u"<Page 1 of 2>", unicode(p)) - self.assertEqual([1, 2, 3, 4, 5], p.object_list) - self.assertTrue(p.has_next()) - self.assertFalse(p.has_previous()) - self.assertTrue(p.has_other_pages()) - self.assertEqual(2, p.next_page_number()) - self.assertEqual(0, p.previous_page_number()) - self.assertEqual(1, p.start_index()) - self.assertEqual(5, p.end_index()) - - def test_paginate_misc_classes(self): - # Paginator can be passed other objects with a count() method. - paginator = Paginator(CountContainer(), 10) - self.assertEqual(42, paginator.count) - self.assertEqual(5, paginator.num_pages) - self.assertEqual([1, 2, 3, 4, 5], paginator.page_range) - - # Paginator can be passed other objects that implement __len__. - paginator = Paginator(LenContainer(), 10) - self.assertEqual(42, paginator.count) - self.assertEqual(5, paginator.num_pages) - self.assertEqual([1, 2, 3, 4, 5], paginator.page_range) diff --git a/parts/django/tests/modeltests/properties/__init__.py b/parts/django/tests/modeltests/properties/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/properties/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/properties/models.py b/parts/django/tests/modeltests/properties/models.py deleted file mode 100644 index 390efe3..0000000 --- a/parts/django/tests/modeltests/properties/models.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -22. Using properties on models - -Use properties on models just like on any other Python object. -""" - -from django.db import models - -class Person(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - - def _get_full_name(self): - return "%s %s" % (self.first_name, self.last_name) - - def _set_full_name(self, combined_name): - self.first_name, self.last_name = combined_name.split(' ', 1) - - full_name = property(_get_full_name) - - full_name_2 = property(_get_full_name, _set_full_name) diff --git a/parts/django/tests/modeltests/properties/tests.py b/parts/django/tests/modeltests/properties/tests.py deleted file mode 100644 index e31ac58..0000000 --- a/parts/django/tests/modeltests/properties/tests.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.test import TestCase -from models import Person - -class PropertyTests(TestCase): - - def setUp(self): - self.a = Person(first_name='John', last_name='Lennon') - self.a.save() - - def test_getter(self): - self.assertEqual(self.a.full_name, 'John Lennon') - - def test_setter(self): - # The "full_name" property hasn't provided a "set" method. - self.assertRaises(AttributeError, setattr, self.a, 'full_name', 'Paul McCartney') - - # But "full_name_2" has, and it can be used to initialise the class. - a2 = Person(full_name_2 = 'Paul McCartney') - a2.save() - self.assertEqual(a2.first_name, 'Paul') diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/__init__.py b/parts/django/tests/modeltests/proxy_model_inheritance/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/app1/__init__.py b/parts/django/tests/modeltests/proxy_model_inheritance/app1/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/app1/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/app1/models.py b/parts/django/tests/modeltests/proxy_model_inheritance/app1/models.py deleted file mode 100644 index 59a9ac7..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/app1/models.py +++ /dev/null @@ -1,5 +0,0 @@ -from app2.models import NiceModel - -class ProxyModel(NiceModel): - class Meta: - proxy = True diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/app2/__init__.py b/parts/django/tests/modeltests/proxy_model_inheritance/app2/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/app2/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/app2/models.py b/parts/django/tests/modeltests/proxy_model_inheritance/app2/models.py deleted file mode 100644 index 549cd07..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/app2/models.py +++ /dev/null @@ -1,4 +0,0 @@ -from django.db import models - -class NiceModel(models.Model): - pass diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/models.py b/parts/django/tests/modeltests/proxy_model_inheritance/models.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/models.py +++ /dev/null diff --git a/parts/django/tests/modeltests/proxy_model_inheritance/tests.py b/parts/django/tests/modeltests/proxy_model_inheritance/tests.py deleted file mode 100644 index b682851..0000000 --- a/parts/django/tests/modeltests/proxy_model_inheritance/tests.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -XX. Proxy model inheritance - -Proxy model inheritance across apps can result in syncdb not creating the table -for the proxied model (as described in #12286). This test creates two dummy -apps and calls syncdb, then verifies that the table has been created. -""" - -import os -import sys - -from django.conf import settings, Settings -from django.core.management import call_command -from django.db.models.loading import load_app -from django.test import TransactionTestCase - -class ProxyModelInheritanceTests(TransactionTestCase): - - def setUp(self): - self.old_sys_path = sys.path[:] - sys.path.append(os.path.dirname(os.path.abspath(__file__))) - self.old_installed_apps = settings.INSTALLED_APPS - settings.INSTALLED_APPS = ('app1', 'app2') - map(load_app, settings.INSTALLED_APPS) - call_command('syncdb', verbosity=0) - global ProxyModel, NiceModel - from app1.models import ProxyModel - from app2.models import NiceModel - - def tearDown(self): - settings.INSTALLED_APPS = self.old_installed_apps - sys.path = self.old_sys_path - - def test_table_exists(self): - self.assertEquals(NiceModel.objects.all().count(), 0) - self.assertEquals(ProxyModel.objects.all().count(), 0) diff --git a/parts/django/tests/modeltests/proxy_models/__init__.py b/parts/django/tests/modeltests/proxy_models/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/proxy_models/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/proxy_models/fixtures/mypeople.json b/parts/django/tests/modeltests/proxy_models/fixtures/mypeople.json deleted file mode 100644 index d20c8f2..0000000 --- a/parts/django/tests/modeltests/proxy_models/fixtures/mypeople.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "pk": 100, - "model": "proxy_models.myperson", - "fields": { - "name": "Elvis Presley" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/proxy_models/models.py b/parts/django/tests/modeltests/proxy_models/models.py deleted file mode 100644 index 90d54d9..0000000 --- a/parts/django/tests/modeltests/proxy_models/models.py +++ /dev/null @@ -1,164 +0,0 @@ -""" -By specifying the 'proxy' Meta attribute, model subclasses can specify that -they will take data directly from the table of their base class table rather -than using a new table of their own. This allows them to act as simple proxies, -providing a modified interface to the data from the base class. -""" - -from django.contrib.contenttypes.models import ContentType -from django.db import models - - -# A couple of managers for testing managing overriding in proxy model cases. - -class PersonManager(models.Manager): - def get_query_set(self): - return super(PersonManager, self).get_query_set().exclude(name="fred") - -class SubManager(models.Manager): - def get_query_set(self): - return super(SubManager, self).get_query_set().exclude(name="wilma") - -class Person(models.Model): - """ - A simple concrete base class. - """ - name = models.CharField(max_length=50) - - objects = PersonManager() - - def __unicode__(self): - return self.name - -class Abstract(models.Model): - """ - A simple abstract base class, to be used for error checking. - """ - data = models.CharField(max_length=10) - - class Meta: - abstract = True - -class MyPerson(Person): - """ - A proxy subclass, this should not get a new table. Overrides the default - manager. - """ - class Meta: - proxy = True - ordering = ["name"] - - objects = SubManager() - other = PersonManager() - - def has_special_name(self): - return self.name.lower() == "special" - -class ManagerMixin(models.Model): - excluder = SubManager() - - class Meta: - abstract = True - -class OtherPerson(Person, ManagerMixin): - """ - A class with the default manager from Person, plus an secondary manager. - """ - class Meta: - proxy = True - ordering = ["name"] - -class StatusPerson(MyPerson): - """ - A non-proxy subclass of a proxy, it should get a new table. - """ - status = models.CharField(max_length=80) - -# We can even have proxies of proxies (and subclass of those). -class MyPersonProxy(MyPerson): - class Meta: - proxy = True - -class LowerStatusPerson(MyPersonProxy): - status = models.CharField(max_length=80) - -class User(models.Model): - name = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - -class UserProxy(User): - class Meta: - proxy = True - -class UserProxyProxy(UserProxy): - class Meta: - proxy = True - -# We can still use `select_related()` to include related models in our querysets. -class Country(models.Model): - name = models.CharField(max_length=50) - -class State(models.Model): - name = models.CharField(max_length=50) - country = models.ForeignKey(Country) - - def __unicode__(self): - return self.name - -class StateProxy(State): - class Meta: - proxy = True - -# Proxy models still works with filters (on related fields) -# and select_related, even when mixed with model inheritance -class BaseUser(models.Model): - name = models.CharField(max_length=255) - -class TrackerUser(BaseUser): - status = models.CharField(max_length=50) - -class ProxyTrackerUser(TrackerUser): - class Meta: - proxy = True - - -class Issue(models.Model): - summary = models.CharField(max_length=255) - assignee = models.ForeignKey(TrackerUser) - - def __unicode__(self): - return ':'.join((self.__class__.__name__,self.summary,)) - -class Bug(Issue): - version = models.CharField(max_length=50) - reporter = models.ForeignKey(BaseUser) - -class ProxyBug(Bug): - """ - Proxy of an inherited class - """ - class Meta: - proxy = True - - -class ProxyProxyBug(ProxyBug): - """ - A proxy of proxy model with related field - """ - class Meta: - proxy = True - -class Improvement(Issue): - """ - A model that has relation to a proxy model - or to a proxy of proxy model - """ - version = models.CharField(max_length=50) - reporter = models.ForeignKey(ProxyTrackerUser) - associated_bug = models.ForeignKey(ProxyProxyBug) - -class ProxyImprovement(Improvement): - class Meta: - proxy = True
\ No newline at end of file diff --git a/parts/django/tests/modeltests/proxy_models/tests.py b/parts/django/tests/modeltests/proxy_models/tests.py deleted file mode 100644 index 346a2a3..0000000 --- a/parts/django/tests/modeltests/proxy_models/tests.py +++ /dev/null @@ -1,314 +0,0 @@ -from django.test import TestCase -from django.db import models, DEFAULT_DB_ALIAS -from django.db.models import signals -from django.core import management -from django.core.exceptions import FieldError - -from django.contrib.contenttypes.models import ContentType - -from models import MyPerson, Person, StatusPerson, LowerStatusPerson -from models import MyPersonProxy, Abstract, OtherPerson, User, UserProxy -from models import UserProxyProxy, Country, State, StateProxy, TrackerUser -from models import BaseUser, Bug, ProxyTrackerUser, Improvement, ProxyProxyBug -from models import ProxyBug, ProxyImprovement - -class ProxyModelTests(TestCase): - def test_same_manager_queries(self): - """ - The MyPerson model should be generating the same database queries as - the Person model (when the same manager is used in each case). - """ - my_person_sql = MyPerson.other.all().query.get_compiler( - DEFAULT_DB_ALIAS).as_sql() - person_sql = Person.objects.order_by("name").query.get_compiler( - DEFAULT_DB_ALIAS).as_sql() - self.assertEqual(my_person_sql, person_sql) - - def test_inheretance_new_table(self): - """ - The StatusPerson models should have its own table (it's using ORM-level - inheritance). - """ - sp_sql = StatusPerson.objects.all().query.get_compiler( - DEFAULT_DB_ALIAS).as_sql() - p_sql = Person.objects.all().query.get_compiler( - DEFAULT_DB_ALIAS).as_sql() - self.assertNotEqual(sp_sql, p_sql) - - def test_basic_proxy(self): - """ - Creating a Person makes them accessible through the MyPerson proxy. - """ - Person.objects.create(name="Foo McBar") - self.assertEqual(len(Person.objects.all()), 1) - self.assertEqual(len(MyPerson.objects.all()), 1) - self.assertEqual(MyPerson.objects.get(name="Foo McBar").id, 1) - self.assertFalse(MyPerson.objects.get(id=1).has_special_name()) - - def test_no_proxy(self): - """ - Person is not proxied by StatusPerson subclass. - """ - Person.objects.create(name="Foo McBar") - self.assertEqual(list(StatusPerson.objects.all()), []) - - def test_basic_proxy_reverse(self): - """ - A new MyPerson also shows up as a standard Person. - """ - MyPerson.objects.create(name="Bazza del Frob") - self.assertEqual(len(MyPerson.objects.all()), 1) - self.assertEqual(len(Person.objects.all()), 1) - - LowerStatusPerson.objects.create(status="low", name="homer") - lsps = [lsp.name for lsp in LowerStatusPerson.objects.all()] - self.assertEqual(lsps, ["homer"]) - - def test_correct_type_proxy_of_proxy(self): - """ - Correct type when querying a proxy of proxy - """ - Person.objects.create(name="Foo McBar") - MyPerson.objects.create(name="Bazza del Frob") - LowerStatusPerson.objects.create(status="low", name="homer") - pp = sorted([mpp.name for mpp in MyPersonProxy.objects.all()]) - self.assertEqual(pp, ['Bazza del Frob', 'Foo McBar', 'homer']) - - def test_proxy_included_in_ancestors(self): - """ - Proxy models are included in the ancestors for a model's DoesNotExist - and MultipleObjectsReturned - """ - Person.objects.create(name="Foo McBar") - MyPerson.objects.create(name="Bazza del Frob") - LowerStatusPerson.objects.create(status="low", name="homer") - max_id = Person.objects.aggregate(max_id=models.Max('id'))['max_id'] - - self.assertRaises(Person.DoesNotExist, - MyPersonProxy.objects.get, - name='Zathras' - ) - self.assertRaises(Person.MultipleObjectsReturned, - MyPersonProxy.objects.get, - id__lt=max_id+1 - ) - self.assertRaises(Person.DoesNotExist, - StatusPerson.objects.get, - name='Zathras' - ) - - sp1 = StatusPerson.objects.create(name='Bazza Jr.') - sp2 = StatusPerson.objects.create(name='Foo Jr.') - max_id = Person.objects.aggregate(max_id=models.Max('id'))['max_id'] - - self.assertRaises(Person.MultipleObjectsReturned, - StatusPerson.objects.get, - id__lt=max_id+1 - ) - - def test_abc(self): - """ - All base classes must be non-abstract - """ - def build_abc(): - class NoAbstract(Abstract): - class Meta: - proxy = True - self.assertRaises(TypeError, build_abc) - - def test_no_cbc(self): - """ - The proxy must actually have one concrete base class - """ - def build_no_cbc(): - class TooManyBases(Person, Abstract): - class Meta: - proxy = True - self.assertRaises(TypeError, build_no_cbc) - - def test_no_base_classes(self): - def build_no_base_classes(): - class NoBaseClasses(models.Model): - class Meta: - proxy = True - self.assertRaises(TypeError, build_no_base_classes) - - def test_new_fields(self): - def build_new_fields(): - class NoNewFields(Person): - newfield = models.BooleanField() - class Meta: - proxy = True - self.assertRaises(FieldError, build_new_fields) - - def test_myperson_manager(self): - Person.objects.create(name="fred") - Person.objects.create(name="wilma") - Person.objects.create(name="barney") - - resp = [p.name for p in MyPerson.objects.all()] - self.assertEqual(resp, ['barney', 'fred']) - - resp = [p.name for p in MyPerson._default_manager.all()] - self.assertEqual(resp, ['barney', 'fred']) - - def test_otherperson_manager(self): - Person.objects.create(name="fred") - Person.objects.create(name="wilma") - Person.objects.create(name="barney") - - resp = [p.name for p in OtherPerson.objects.all()] - self.assertEqual(resp, ['barney', 'wilma']) - - resp = [p.name for p in OtherPerson.excluder.all()] - self.assertEqual(resp, ['barney', 'fred']) - - resp = [p.name for p in OtherPerson._default_manager.all()] - self.assertEqual(resp, ['barney', 'wilma']) - - def test_proxy_model_signals(self): - """ - Test save signals for proxy models - """ - output = [] - - def make_handler(model, event): - def _handler(*args, **kwargs): - output.append('%s %s save' % (model, event)) - return _handler - - h1 = make_handler('MyPerson', 'pre') - h2 = make_handler('MyPerson', 'post') - h3 = make_handler('Person', 'pre') - h4 = make_handler('Person', 'post') - - signals.pre_save.connect(h1, sender=MyPerson) - signals.post_save.connect(h2, sender=MyPerson) - signals.pre_save.connect(h3, sender=Person) - signals.post_save.connect(h4, sender=Person) - - dino = MyPerson.objects.create(name=u"dino") - self.assertEqual(output, [ - 'MyPerson pre save', - 'MyPerson post save' - ]) - - output = [] - - h5 = make_handler('MyPersonProxy', 'pre') - h6 = make_handler('MyPersonProxy', 'post') - - signals.pre_save.connect(h5, sender=MyPersonProxy) - signals.post_save.connect(h6, sender=MyPersonProxy) - - dino = MyPersonProxy.objects.create(name=u"pebbles") - - self.assertEqual(output, [ - 'MyPersonProxy pre save', - 'MyPersonProxy post save' - ]) - - signals.pre_save.disconnect(h1, sender=MyPerson) - signals.post_save.disconnect(h2, sender=MyPerson) - signals.pre_save.disconnect(h3, sender=Person) - signals.post_save.disconnect(h4, sender=Person) - signals.pre_save.disconnect(h5, sender=MyPersonProxy) - signals.post_save.disconnect(h6, sender=MyPersonProxy) - - def test_content_type(self): - ctype = ContentType.objects.get_for_model - self.assertTrue(ctype(Person) is ctype(OtherPerson)) - - def test_user_userproxy_userproxyproxy(self): - User.objects.create(name='Bruce') - - resp = [u.name for u in User.objects.all()] - self.assertEqual(resp, ['Bruce']) - - resp = [u.name for u in UserProxy.objects.all()] - self.assertEqual(resp, ['Bruce']) - - resp = [u.name for u in UserProxyProxy.objects.all()] - self.assertEqual(resp, ['Bruce']) - - def test_proxy_delete(self): - """ - Proxy objects can be deleted - """ - User.objects.create(name='Bruce') - u2 = UserProxy.objects.create(name='George') - - resp = [u.name for u in UserProxy.objects.all()] - self.assertEqual(resp, ['Bruce', 'George']) - - u2.delete() - - resp = [u.name for u in UserProxy.objects.all()] - self.assertEqual(resp, ['Bruce']) - - def test_select_related(self): - """ - We can still use `select_related()` to include related models in our - querysets. - """ - country = Country.objects.create(name='Australia') - state = State.objects.create(name='New South Wales', country=country) - - resp = [s.name for s in State.objects.select_related()] - self.assertEqual(resp, ['New South Wales']) - - resp = [s.name for s in StateProxy.objects.select_related()] - self.assertEqual(resp, ['New South Wales']) - - self.assertEqual(StateProxy.objects.get(name='New South Wales').name, - 'New South Wales') - - resp = StateProxy.objects.select_related().get(name='New South Wales') - self.assertEqual(resp.name, 'New South Wales') - - def test_proxy_bug(self): - contributor = TrackerUser.objects.create(name='Contributor', - status='contrib') - someone = BaseUser.objects.create(name='Someone') - Bug.objects.create(summary='fix this', version='1.1beta', - assignee=contributor, reporter=someone) - pcontributor = ProxyTrackerUser.objects.create(name='OtherContributor', - status='proxy') - Improvement.objects.create(summary='improve that', version='1.1beta', - assignee=contributor, reporter=pcontributor, - associated_bug=ProxyProxyBug.objects.all()[0]) - - # Related field filter on proxy - resp = ProxyBug.objects.get(version__icontains='beta') - self.assertEqual(repr(resp), '<ProxyBug: ProxyBug:fix this>') - - # Select related + filter on proxy - resp = ProxyBug.objects.select_related().get(version__icontains='beta') - self.assertEqual(repr(resp), '<ProxyBug: ProxyBug:fix this>') - - # Proxy of proxy, select_related + filter - resp = ProxyProxyBug.objects.select_related().get( - version__icontains='beta' - ) - self.assertEqual(repr(resp), '<ProxyProxyBug: ProxyProxyBug:fix this>') - - # Select related + filter on a related proxy field - resp = ProxyImprovement.objects.select_related().get( - reporter__name__icontains='butor' - ) - self.assertEqual(repr(resp), - '<ProxyImprovement: ProxyImprovement:improve that>' - ) - - # Select related + filter on a related proxy of proxy field - resp = ProxyImprovement.objects.select_related().get( - associated_bug__summary__icontains='fix' - ) - self.assertEqual(repr(resp), - '<ProxyImprovement: ProxyImprovement:improve that>' - ) - - def test_proxy_load_from_fixture(self): - management.call_command('loaddata', 'mypeople.json', verbosity=0, commit=False) - p = MyPerson.objects.get(pk=100) - self.assertEqual(p.name, 'Elvis Presley') diff --git a/parts/django/tests/modeltests/raw_query/__init__.py b/parts/django/tests/modeltests/raw_query/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/raw_query/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/raw_query/fixtures/raw_query_books.json b/parts/django/tests/modeltests/raw_query/fixtures/raw_query_books.json deleted file mode 100644 index 35879aa..0000000 --- a/parts/django/tests/modeltests/raw_query/fixtures/raw_query_books.json +++ /dev/null @@ -1,110 +0,0 @@ -[ - { - "pk": 1, - "model": "raw_query.author", - "fields": { - "dob": "1950-09-20", - "first_name": "Joe", - "last_name": "Smith" - } - }, - { - "pk": 2, - "model": "raw_query.author", - "fields": { - "dob": "1920-04-02", - "first_name": "Jill", - "last_name": "Doe" - } - }, - { - "pk": 3, - "model": "raw_query.author", - "fields": { - "dob": "1986-01-25", - "first_name": "Bob", - "last_name": "Smith" - } - }, - { - "pk": 4, - "model": "raw_query.author", - "fields": { - "dob": "1932-05-10", - "first_name": "Bill", - "last_name": "Jones" - } - }, - { - "pk": 1, - "model": "raw_query.book", - "fields": { - "author": 1, - "title": "The awesome book", - "paperback": false, - "opening_line": "It was a bright cold day in April and the clocks were striking thirteen." - } - }, - { - "pk": 2, - "model": "raw_query.book", - "fields": { - "author": 1, - "title": "The horrible book", - "paperback": true, - "opening_line": "On an evening in the latter part of May a middle-aged man was walking homeward from Shaston to the village of Marlott, in the adjoining Vale of Blakemore, or Blackmoor." - } - }, - { - "pk": 3, - "model": "raw_query.book", - "fields": { - "author": 1, - "title": "Another awesome book", - "paperback": false, - "opening_line": "A squat grey building of only thirty-four stories." - } - }, - { - "pk": 4, - "model": "raw_query.book", - "fields": { - "author": 3, - "title": "Some other book", - "paperback": true, - "opening_line": "It was the day my grandmother exploded." - } - }, - { - "pk": 1, - "model": "raw_query.coffee", - "fields": { - "brand": "dunkin doughnuts" - } - }, - { - "pk": 2, - "model": "raw_query.coffee", - "fields": { - "brand": "starbucks" - } - }, - { - "pk": 1, - "model": "raw_query.reviewer", - "fields": { - "reviewed": [ - 2, - 3, - 4 - ] - } - }, - { - "pk": 2, - "model": "raw_query.reviewer", - "fields": { - "reviewed": [] - } - } -] diff --git a/parts/django/tests/modeltests/raw_query/models.py b/parts/django/tests/modeltests/raw_query/models.py deleted file mode 100644 index bb42b5b..0000000 --- a/parts/django/tests/modeltests/raw_query/models.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.db import models - -class Author(models.Model): - first_name = models.CharField(max_length=255) - last_name = models.CharField(max_length=255) - dob = models.DateField() - - def __init__(self, *args, **kwargs): - super(Author, self).__init__(*args, **kwargs) - # Protect against annotations being passed to __init__ -- - # this'll make the test suite get angry if annotations aren't - # treated differently than fields. - for k in kwargs: - assert k in [f.attname for f in self._meta.fields], \ - "Author.__init__ got an unexpected paramater: %s" % k - -class Book(models.Model): - title = models.CharField(max_length=255) - author = models.ForeignKey(Author) - paperback = models.BooleanField() - opening_line = models.TextField() - -class Coffee(models.Model): - brand = models.CharField(max_length=255, db_column="name") - -class Reviewer(models.Model): - reviewed = models.ManyToManyField(Book) - -class FriendlyAuthor(Author): - pass diff --git a/parts/django/tests/modeltests/raw_query/tests.py b/parts/django/tests/modeltests/raw_query/tests.py deleted file mode 100644 index a1e7edb..0000000 --- a/parts/django/tests/modeltests/raw_query/tests.py +++ /dev/null @@ -1,236 +0,0 @@ -from datetime import date - -from django.conf import settings -from django.db import connection -from django.db.models.sql.query import InvalidQuery -from django.test import TestCase - -from models import Author, Book, Coffee, Reviewer, FriendlyAuthor - - -class RawQueryTests(TestCase): - fixtures = ['raw_query_books.json'] - - def assertSuccessfulRawQuery(self, model, query, expected_results, - expected_annotations=(), params=[], translations=None): - """ - Execute the passed query against the passed model and check the output - """ - results = list(model.objects.raw(query, params=params, translations=translations)) - self.assertProcessed(model, results, expected_results, expected_annotations) - self.assertAnnotations(results, expected_annotations) - - def assertProcessed(self, model, results, orig, expected_annotations=()): - """ - Compare the results of a raw query against expected results - """ - self.assertEqual(len(results), len(orig)) - for index, item in enumerate(results): - orig_item = orig[index] - for annotation in expected_annotations: - setattr(orig_item, *annotation) - - for field in model._meta.fields: - # Check that all values on the model are equal - self.assertEquals(getattr(item,field.attname), - getattr(orig_item,field.attname)) - # This includes checking that they are the same type - self.assertEquals(type(getattr(item,field.attname)), - type(getattr(orig_item,field.attname))) - - def assertNoAnnotations(self, results): - """ - Check that the results of a raw query contain no annotations - """ - self.assertAnnotations(results, ()) - - def assertAnnotations(self, results, expected_annotations): - """ - Check that the passed raw query results contain the expected - annotations - """ - if expected_annotations: - for index, result in enumerate(results): - annotation, value = expected_annotations[index] - self.assertTrue(hasattr(result, annotation)) - self.assertEqual(getattr(result, annotation), value) - - def assert_num_queries(self, n, func, *args, **kwargs): - old_DEBUG = settings.DEBUG - settings.DEBUG = True - starting_queries = len(connection.queries) - try: - func(*args, **kwargs) - finally: - settings.DEBUG = old_DEBUG - self.assertEqual(starting_queries + n, len(connection.queries)) - - def testSimpleRawQuery(self): - """ - Basic test of raw query with a simple database query - """ - query = "SELECT * FROM raw_query_author" - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors) - - def testRawQueryLazy(self): - """ - Raw queries are lazy: they aren't actually executed until they're - iterated over. - """ - q = Author.objects.raw('SELECT * FROM raw_query_author') - self.assert_(q.query.cursor is None) - list(q) - self.assert_(q.query.cursor is not None) - - def testFkeyRawQuery(self): - """ - Test of a simple raw query against a model containing a foreign key - """ - query = "SELECT * FROM raw_query_book" - books = Book.objects.all() - self.assertSuccessfulRawQuery(Book, query, books) - - def testDBColumnHandler(self): - """ - Test of a simple raw query against a model containing a field with - db_column defined. - """ - query = "SELECT * FROM raw_query_coffee" - coffees = Coffee.objects.all() - self.assertSuccessfulRawQuery(Coffee, query, coffees) - - def testOrderHandler(self): - """ - Test of raw raw query's tolerance for columns being returned in any - order - """ - selects = ( - ('dob, last_name, first_name, id'), - ('last_name, dob, first_name, id'), - ('first_name, last_name, dob, id'), - ) - - for select in selects: - query = "SELECT %s FROM raw_query_author" % select - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors) - - def testTranslations(self): - """ - Test of raw query's optional ability to translate unexpected result - column names to specific model fields - """ - query = "SELECT first_name AS first, last_name AS last, dob, id FROM raw_query_author" - translations = {'first': 'first_name', 'last': 'last_name'} - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors, translations=translations) - - def testParams(self): - """ - Test passing optional query parameters - """ - query = "SELECT * FROM raw_query_author WHERE first_name = %s" - author = Author.objects.all()[2] - params = [author.first_name] - results = list(Author.objects.raw(query, params=params)) - self.assertProcessed(Author, results, [author]) - self.assertNoAnnotations(results) - self.assertEqual(len(results), 1) - - def testManyToMany(self): - """ - Test of a simple raw query against a model containing a m2m field - """ - query = "SELECT * FROM raw_query_reviewer" - reviewers = Reviewer.objects.all() - self.assertSuccessfulRawQuery(Reviewer, query, reviewers) - - def testExtraConversions(self): - """ - Test to insure that extra translations are ignored. - """ - query = "SELECT * FROM raw_query_author" - translations = {'something': 'else'} - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors, translations=translations) - - def testMissingFields(self): - query = "SELECT id, first_name, dob FROM raw_query_author" - for author in Author.objects.raw(query): - self.assertNotEqual(author.first_name, None) - # last_name isn't given, but it will be retrieved on demand - self.assertNotEqual(author.last_name, None) - - def testMissingFieldsWithoutPK(self): - query = "SELECT first_name, dob FROM raw_query_author" - try: - list(Author.objects.raw(query)) - self.fail('Query without primary key should fail') - except InvalidQuery: - pass - - def testAnnotations(self): - query = "SELECT a.*, count(b.id) as book_count FROM raw_query_author a LEFT JOIN raw_query_book b ON a.id = b.author_id GROUP BY a.id, a.first_name, a.last_name, a.dob ORDER BY a.id" - expected_annotations = ( - ('book_count', 3), - ('book_count', 0), - ('book_count', 1), - ('book_count', 0), - ) - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors, expected_annotations) - - def testInvalidQuery(self): - query = "UPDATE raw_query_author SET first_name='thing' WHERE first_name='Joe'" - self.assertRaises(InvalidQuery, Author.objects.raw, query) - - def testWhiteSpaceQuery(self): - query = " SELECT * FROM raw_query_author" - authors = Author.objects.all() - self.assertSuccessfulRawQuery(Author, query, authors) - - def testMultipleIterations(self): - query = "SELECT * FROM raw_query_author" - normal_authors = Author.objects.all() - raw_authors = Author.objects.raw(query) - - # First Iteration - first_iterations = 0 - for index, raw_author in enumerate(raw_authors): - self.assertEqual(normal_authors[index], raw_author) - first_iterations += 1 - - # Second Iteration - second_iterations = 0 - for index, raw_author in enumerate(raw_authors): - self.assertEqual(normal_authors[index], raw_author) - second_iterations += 1 - - self.assertEqual(first_iterations, second_iterations) - - def testGetItem(self): - # Indexing on RawQuerySets - query = "SELECT * FROM raw_query_author ORDER BY id ASC" - third_author = Author.objects.raw(query)[2] - self.assertEqual(third_author.first_name, 'Bob') - - first_two = Author.objects.raw(query)[0:2] - self.assertEquals(len(first_two), 2) - - self.assertRaises(TypeError, lambda: Author.objects.raw(query)['test']) - - def test_inheritance(self): - # date is the end of the Cuban Missile Crisis, I have no idea when - # Wesley was bron - f = FriendlyAuthor.objects.create(first_name="Wesley", last_name="Chun", - dob=date(1962, 10, 28)) - query = "SELECT * FROM raw_query_friendlyauthor" - self.assertEqual( - [o.pk for o in FriendlyAuthor.objects.raw(query)], [f.pk] - ) - - def test_query_count(self): - self.assert_num_queries(1, - list, Author.objects.raw("SELECT * FROM raw_query_author") - ) diff --git a/parts/django/tests/modeltests/reserved_names/__init__.py b/parts/django/tests/modeltests/reserved_names/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/reserved_names/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/reserved_names/models.py b/parts/django/tests/modeltests/reserved_names/models.py deleted file mode 100644 index d8c1238..0000000 --- a/parts/django/tests/modeltests/reserved_names/models.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -18. Using SQL reserved names - -Need to use a reserved SQL name as a column name or table name? Need to include -a hyphen in a column or table name? No problem. Django quotes names -appropriately behind the scenes, so your database won't complain about -reserved-name usage. -""" - -from django.db import models - -class Thing(models.Model): - when = models.CharField(max_length=1, primary_key=True) - join = models.CharField(max_length=1) - like = models.CharField(max_length=1) - drop = models.CharField(max_length=1) - alter = models.CharField(max_length=1) - having = models.CharField(max_length=1) - where = models.DateField(max_length=1) - has_hyphen = models.CharField(max_length=1, db_column='has-hyphen') - class Meta: - db_table = 'select' - - def __unicode__(self): - return self.when
\ No newline at end of file diff --git a/parts/django/tests/modeltests/reserved_names/tests.py b/parts/django/tests/modeltests/reserved_names/tests.py deleted file mode 100644 index b7e4867..0000000 --- a/parts/django/tests/modeltests/reserved_names/tests.py +++ /dev/null @@ -1,48 +0,0 @@ -import datetime - -from django.test import TestCase - -from models import Thing - -class ReservedNameTests(TestCase): - def generate(self): - day1 = datetime.date(2005, 1, 1) - t = Thing.objects.create(when='a', join='b', like='c', drop='d', - alter='e', having='f', where=day1, has_hyphen='h') - day2 = datetime.date(2006, 2, 2) - u = Thing.objects.create(when='h', join='i', like='j', drop='k', - alter='l', having='m', where=day2) - - def test_simple(self): - day1 = datetime.date(2005, 1, 1) - t = Thing.objects.create(when='a', join='b', like='c', drop='d', - alter='e', having='f', where=day1, has_hyphen='h') - self.assertEqual(t.when, 'a') - - day2 = datetime.date(2006, 2, 2) - u = Thing.objects.create(when='h', join='i', like='j', drop='k', - alter='l', having='m', where=day2) - self.assertEqual(u.when, 'h') - - def test_order_by(self): - self.generate() - things = [t.when for t in Thing.objects.order_by('when')] - self.assertEqual(things, ['a', 'h']) - - def test_fields(self): - self.generate() - v = Thing.objects.get(pk='a') - self.assertEqual(v.join, 'b') - self.assertEqual(v.where, datetime.date(year=2005, month=1, day=1)) - - def test_dates(self): - self.generate() - resp = Thing.objects.dates('where', 'year') - self.assertEqual(list(resp), [ - datetime.datetime(2005, 1, 1, 0, 0), - datetime.datetime(2006, 1, 1, 0, 0), - ]) - - def test_month_filter(self): - self.generate() - self.assertEqual(Thing.objects.filter(where__month=1)[0].when, 'a') diff --git a/parts/django/tests/modeltests/reverse_lookup/__init__.py b/parts/django/tests/modeltests/reverse_lookup/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/reverse_lookup/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/reverse_lookup/models.py b/parts/django/tests/modeltests/reverse_lookup/models.py deleted file mode 100644 index 2ffdc39..0000000 --- a/parts/django/tests/modeltests/reverse_lookup/models.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -25. Reverse lookups - -This demonstrates the reverse lookup features of the database API. -""" - -from django.db import models - -class User(models.Model): - name = models.CharField(max_length=200) - - def __unicode__(self): - return self.name - -class Poll(models.Model): - question = models.CharField(max_length=200) - creator = models.ForeignKey(User) - - def __unicode__(self): - return self.question - -class Choice(models.Model): - name = models.CharField(max_length=100) - poll = models.ForeignKey(Poll, related_name="poll_choice") - related_poll = models.ForeignKey(Poll, related_name="related_choice") - - def __unicode__(self): - return self.name diff --git a/parts/django/tests/modeltests/reverse_lookup/tests.py b/parts/django/tests/modeltests/reverse_lookup/tests.py deleted file mode 100644 index 9a6e306..0000000 --- a/parts/django/tests/modeltests/reverse_lookup/tests.py +++ /dev/null @@ -1,49 +0,0 @@ -from django.test import TestCase -from django.core.exceptions import FieldError - -from models import User, Poll, Choice - -class ReverseLookupTests(TestCase): - - def setUp(self): - john = User.objects.create(name="John Doe") - jim = User.objects.create(name="Jim Bo") - first_poll = Poll.objects.create( - question="What's the first question?", - creator=john - ) - second_poll = Poll.objects.create( - question="What's the second question?", - creator=jim - ) - new_choice = Choice.objects.create( - poll=first_poll, - related_poll=second_poll, - name="This is the answer." - ) - - def test_reverse_by_field(self): - u1 = User.objects.get( - poll__question__exact="What's the first question?" - ) - self.assertEqual(u1.name, "John Doe") - - u2 = User.objects.get( - poll__question__exact="What's the second question?" - ) - self.assertEqual(u2.name, "Jim Bo") - - def test_reverse_by_related_name(self): - p1 = Poll.objects.get(poll_choice__name__exact="This is the answer.") - self.assertEqual(p1.question, "What's the first question?") - - p2 = Poll.objects.get( - related_choice__name__exact="This is the answer.") - self.assertEqual(p2.question, "What's the second question?") - - def test_reverse_field_name_disallowed(self): - """ - If a related_name is given you can't use the field name instead - """ - self.assertRaises(FieldError, Poll.objects.get, - choice__name__exact="This is the answer") diff --git a/parts/django/tests/modeltests/save_delete_hooks/__init__.py b/parts/django/tests/modeltests/save_delete_hooks/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/save_delete_hooks/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/save_delete_hooks/models.py b/parts/django/tests/modeltests/save_delete_hooks/models.py deleted file mode 100644 index 515c7f6..0000000 --- a/parts/django/tests/modeltests/save_delete_hooks/models.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -13. Adding hooks before/after saving and deleting - -To execute arbitrary code around ``save()`` and ``delete()``, just subclass -the methods. -""" - -from django.db import models - - -class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=20) - - def __init__(self, *args, **kwargs): - super(Person, self).__init__(*args, **kwargs) - self.data = [] - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) - - def save(self, *args, **kwargs): - self.data.append("Before save") - # Call the "real" save() method - super(Person, self).save(*args, **kwargs) - self.data.append("After save") - - def delete(self): - self.data.append("Before deletion") - # Call the "real" delete() method - super(Person, self).delete() - self.data.append("After deletion") diff --git a/parts/django/tests/modeltests/save_delete_hooks/tests.py b/parts/django/tests/modeltests/save_delete_hooks/tests.py deleted file mode 100644 index dc7b8ee..0000000 --- a/parts/django/tests/modeltests/save_delete_hooks/tests.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.test import TestCase - -from models import Person - - -class SaveDeleteHookTests(TestCase): - def test_basic(self): - p = Person(first_name="John", last_name="Smith") - self.assertEqual(p.data, []) - p.save() - self.assertEqual(p.data, [ - "Before save", - "After save", - ]) - - self.assertQuerysetEqual( - Person.objects.all(), [ - "John Smith", - ], - unicode - ) - - p.delete() - self.assertEqual(p.data, [ - "Before save", - "After save", - "Before deletion", - "After deletion", - ]) - self.assertQuerysetEqual(Person.objects.all(), []) diff --git a/parts/django/tests/modeltests/select_related/__init__.py b/parts/django/tests/modeltests/select_related/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/select_related/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/select_related/models.py b/parts/django/tests/modeltests/select_related/models.py deleted file mode 100644 index 3c2e772..0000000 --- a/parts/django/tests/modeltests/select_related/models.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -41. Tests for select_related() - -``select_related()`` follows all relationships and pre-caches any foreign key -values so that complex trees can be fetched in a single query. However, this -isn't always a good idea, so the ``depth`` argument control how many "levels" -the select-related behavior will traverse. -""" - -from django.db import models - -# Who remembers high school biology? - -class Domain(models.Model): - name = models.CharField(max_length=50) - def __unicode__(self): - return self.name - -class Kingdom(models.Model): - name = models.CharField(max_length=50) - domain = models.ForeignKey(Domain) - def __unicode__(self): - return self.name - -class Phylum(models.Model): - name = models.CharField(max_length=50) - kingdom = models.ForeignKey(Kingdom) - def __unicode__(self): - return self.name - -class Klass(models.Model): - name = models.CharField(max_length=50) - phylum = models.ForeignKey(Phylum) - def __unicode__(self): - return self.name - -class Order(models.Model): - name = models.CharField(max_length=50) - klass = models.ForeignKey(Klass) - def __unicode__(self): - return self.name - -class Family(models.Model): - name = models.CharField(max_length=50) - order = models.ForeignKey(Order) - def __unicode__(self): - return self.name - -class Genus(models.Model): - name = models.CharField(max_length=50) - family = models.ForeignKey(Family) - def __unicode__(self): - return self.name - -class Species(models.Model): - name = models.CharField(max_length=50) - genus = models.ForeignKey(Genus) - def __unicode__(self): - return self.name
\ No newline at end of file diff --git a/parts/django/tests/modeltests/select_related/tests.py b/parts/django/tests/modeltests/select_related/tests.py deleted file mode 100644 index 72b3ab2..0000000 --- a/parts/django/tests/modeltests/select_related/tests.py +++ /dev/null @@ -1,166 +0,0 @@ -from django.test import TestCase -from django.conf import settings -from django import db - -from models import Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species - -class SelectRelatedTests(TestCase): - - def create_tree(self, stringtree): - """ - Helper to create a complete tree. - """ - names = stringtree.split() - models = [Domain, Kingdom, Phylum, Klass, Order, Family, Genus, Species] - assert len(names) == len(models), (names, models) - - parent = None - for name, model in zip(names, models): - try: - obj = model.objects.get(name=name) - except model.DoesNotExist: - obj = model(name=name) - if parent: - setattr(obj, parent.__class__.__name__.lower(), parent) - obj.save() - parent = obj - - def create_base_data(self): - self.create_tree("Eukaryota Animalia Anthropoda Insecta Diptera Drosophilidae Drosophila melanogaster") - self.create_tree("Eukaryota Animalia Chordata Mammalia Primates Hominidae Homo sapiens") - self.create_tree("Eukaryota Plantae Magnoliophyta Magnoliopsida Fabales Fabaceae Pisum sativum") - self.create_tree("Eukaryota Fungi Basidiomycota Homobasidiomycatae Agaricales Amanitacae Amanita muscaria") - - def setUp(self): - # The test runner sets settings.DEBUG to False, but we want to gather - # queries so we'll set it to True here and reset it at the end of the - # test case. - self.create_base_data() - settings.DEBUG = True - db.reset_queries() - - def tearDown(self): - settings.DEBUG = False - - def test_access_fks_without_select_related(self): - """ - Normally, accessing FKs doesn't fill in related objects - """ - fly = Species.objects.get(name="melanogaster") - domain = fly.genus.family.order.klass.phylum.kingdom.domain - self.assertEqual(domain.name, 'Eukaryota') - self.assertEqual(len(db.connection.queries), 8) - - def test_access_fks_with_select_related(self): - """ - A select_related() call will fill in those related objects without any - extra queries - """ - person = Species.objects.select_related(depth=10).get(name="sapiens") - domain = person.genus.family.order.klass.phylum.kingdom.domain - self.assertEqual(domain.name, 'Eukaryota') - self.assertEqual(len(db.connection.queries), 1) - - def test_list_without_select_related(self): - """ - select_related() also of course applies to entire lists, not just - items. This test verifies the expected behavior without select_related. - """ - world = Species.objects.all() - families = [o.genus.family.name for o in world] - self.assertEqual(sorted(families), [ - 'Amanitacae', - 'Drosophilidae', - 'Fabaceae', - 'Hominidae', - ]) - self.assertEqual(len(db.connection.queries), 9) - - def test_list_with_select_related(self): - """ - select_related() also of course applies to entire lists, not just - items. This test verifies the expected behavior with select_related. - """ - world = Species.objects.all().select_related() - families = [o.genus.family.name for o in world] - self.assertEqual(sorted(families), [ - 'Amanitacae', - 'Drosophilidae', - 'Fabaceae', - 'Hominidae', - ]) - self.assertEqual(len(db.connection.queries), 1) - - def test_depth(self, depth=1, expected=7): - """ - The "depth" argument to select_related() will stop the descent at a - particular level. - """ - pea = Species.objects.select_related(depth=depth).get(name="sativum") - self.assertEqual( - pea.genus.family.order.klass.phylum.kingdom.domain.name, - 'Eukaryota' - ) - # Notice: one fewer queries than above because of depth=1 - self.assertEqual(len(db.connection.queries), expected) - - def test_larger_depth(self): - """ - The "depth" argument to select_related() will stop the descent at a - particular level. This tests a larger depth value. - """ - self.test_depth(depth=5, expected=3) - - def test_list_with_depth(self): - """ - The "depth" argument to select_related() will stop the descent at a - particular level. This can be used on lists as well. - """ - world = Species.objects.all().select_related(depth=2) - orders = [o.genus.family.order.name for o in world] - self.assertEqual(sorted(orders), - ['Agaricales', 'Diptera', 'Fabales', 'Primates']) - self.assertEqual(len(db.connection.queries), 5) - - def test_select_related_with_extra(self): - s = Species.objects.all().select_related(depth=1)\ - .extra(select={'a': 'select_related_species.id + 10'})[0] - self.assertEqual(s.id + 10, s.a) - - def test_certain_fields(self): - """ - The optional fields passed to select_related() control which related - models we pull in. This allows for smaller queries and can act as an - alternative (or, in addition to) the depth parameter. - - In this case, we explicitly say to select the 'genus' and - 'genus.family' models, leading to the same number of queries as before. - """ - world = Species.objects.select_related('genus__family') - families = [o.genus.family.name for o in world] - self.assertEqual(sorted(families), - ['Amanitacae', 'Drosophilidae', 'Fabaceae', 'Hominidae']) - self.assertEqual(len(db.connection.queries), 1) - - def test_more_certain_fields(self): - """ - In this case, we explicitly say to select the 'genus' and - 'genus.family' models, leading to the same number of queries as before. - """ - world = Species.objects.filter(genus__name='Amanita')\ - .select_related('genus__family') - orders = [o.genus.family.order.name for o in world] - self.assertEqual(orders, [u'Agaricales']) - self.assertEqual(len(db.connection.queries), 2) - - def test_field_traversal(self): - s = Species.objects.all().select_related('genus__family__order' - ).order_by('id')[0:1].get().genus.family.order.name - self.assertEqual(s, u'Diptera') - self.assertEqual(len(db.connection.queries), 1) - - def test_depth_fields_fails(self): - self.assertRaises(TypeError, - Species.objects.select_related, - 'genus__family__order', depth=4 - ) diff --git a/parts/django/tests/modeltests/serializers/__init__.py b/parts/django/tests/modeltests/serializers/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/serializers/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/serializers/models.py b/parts/django/tests/modeltests/serializers/models.py deleted file mode 100644 index c12e73f..0000000 --- a/parts/django/tests/modeltests/serializers/models.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -""" -42. Serialization - -``django.core.serializers`` provides interfaces to converting Django -``QuerySet`` objects to and from "flat" data (i.e. strings). -""" - -from decimal import Decimal -from django.db import models - -class Category(models.Model): - name = models.CharField(max_length=20) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - - -class Author(models.Model): - name = models.CharField(max_length=20) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - - -class Article(models.Model): - author = models.ForeignKey(Author) - headline = models.CharField(max_length=50) - pub_date = models.DateTimeField() - categories = models.ManyToManyField(Category) - - class Meta: - ordering = ('pub_date',) - - def __unicode__(self): - return self.headline - - -class AuthorProfile(models.Model): - author = models.OneToOneField(Author, primary_key=True) - date_of_birth = models.DateField() - - def __unicode__(self): - return u"Profile of %s" % self.author - - -class Actor(models.Model): - name = models.CharField(max_length=20, primary_key=True) - - class Meta: - ordering = ('name',) - - def __unicode__(self): - return self.name - - -class Movie(models.Model): - actor = models.ForeignKey(Actor) - title = models.CharField(max_length=50) - price = models.DecimalField(max_digits=6, decimal_places=2, default=Decimal('0.00')) - - class Meta: - ordering = ('title',) - - def __unicode__(self): - return self.title - - -class Score(models.Model): - score = models.FloatField() - - -class Team(object): - def __init__(self, title): - self.title = title - - def __unicode__(self): - raise NotImplementedError("Not so simple") - - def __str__(self): - raise NotImplementedError("Not so simple") - - def to_string(self): - return "%s" % self.title - - -class TeamField(models.CharField): - __metaclass__ = models.SubfieldBase - - def __init__(self): - super(TeamField, self).__init__(max_length=100) - - def get_db_prep_save(self, value): - return unicode(value.title) - - def to_python(self, value): - if isinstance(value, Team): - return value - return Team(value) - - def value_to_string(self, obj): - return self._get_val_from_obj(obj).to_string() - - -class Player(models.Model): - name = models.CharField(max_length=50) - rank = models.IntegerField() - team = TeamField() - - def __unicode__(self): - return u'%s (%d) playing for %s' % (self.name, self.rank, self.team.to_string()) diff --git a/parts/django/tests/modeltests/serializers/tests.py b/parts/django/tests/modeltests/serializers/tests.py deleted file mode 100644 index 9b648a8..0000000 --- a/parts/django/tests/modeltests/serializers/tests.py +++ /dev/null @@ -1,417 +0,0 @@ -# -*- coding: utf-8 -*- -from datetime import datetime -from StringIO import StringIO -from xml.dom import minidom - -from django.core import serializers -from django.db import transaction -from django.test import TestCase, TransactionTestCase, Approximate -from django.utils import simplejson - -from models import Category, Author, Article, AuthorProfile, Actor, \ - Movie, Score, Player, Team - -class SerializersTestBase(object): - @staticmethod - def _comparison_value(value): - return value - - def setUp(self): - sports = Category.objects.create(name="Sports") - music = Category.objects.create(name="Music") - op_ed = Category.objects.create(name="Op-Ed") - - self.joe = Author.objects.create(name="Joe") - self.jane = Author.objects.create(name="Jane") - - self.a1 = Article( - author=self.jane, - headline="Poker has no place on ESPN", - pub_date=datetime(2006, 6, 16, 11, 00) - ) - self.a1.save() - self.a1.categories = [sports, op_ed] - - self.a2 = Article( - author=self.joe, - headline="Time to reform copyright", - pub_date=datetime(2006, 6, 16, 13, 00, 11, 345) - ) - self.a2.save() - self.a2.categories = [music, op_ed] - - def test_serialize(self): - """Tests that basic serialization works.""" - serial_str = serializers.serialize(self.serializer_name, - Article.objects.all()) - self.assertTrue(self._validate_output(serial_str)) - - def test_serializer_roundtrip(self): - """Tests that serialized content can be deserialized.""" - serial_str = serializers.serialize(self.serializer_name, - Article.objects.all()) - models = list(serializers.deserialize(self.serializer_name, serial_str)) - self.assertEqual(len(models), 2) - - def test_altering_serialized_output(self): - """ - Tests the ability to create new objects by - modifying serialized content. - """ - old_headline = "Poker has no place on ESPN" - new_headline = "Poker has no place on television" - serial_str = serializers.serialize(self.serializer_name, - Article.objects.all()) - serial_str = serial_str.replace(old_headline, new_headline) - models = list(serializers.deserialize(self.serializer_name, serial_str)) - - # Prior to saving, old headline is in place - self.assertTrue(Article.objects.filter(headline=old_headline)) - self.assertFalse(Article.objects.filter(headline=new_headline)) - - for model in models: - model.save() - - # After saving, new headline is in place - self.assertTrue(Article.objects.filter(headline=new_headline)) - self.assertFalse(Article.objects.filter(headline=old_headline)) - - def test_one_to_one_as_pk(self): - """ - Tests that if you use your own primary key field - (such as a OneToOneField), it doesn't appear in the - serialized field list - it replaces the pk identifier. - """ - profile = AuthorProfile(author=self.joe, - date_of_birth=datetime(1970,1,1)) - profile.save() - serial_str = serializers.serialize(self.serializer_name, - AuthorProfile.objects.all()) - self.assertFalse(self._get_field_values(serial_str, 'author')) - - for obj in serializers.deserialize(self.serializer_name, serial_str): - self.assertEqual(obj.object.pk, self._comparison_value(self.joe.pk)) - - def test_serialize_field_subset(self): - """Tests that output can be restricted to a subset of fields""" - valid_fields = ('headline','pub_date') - invalid_fields = ("author", "categories") - serial_str = serializers.serialize(self.serializer_name, - Article.objects.all(), - fields=valid_fields) - for field_name in invalid_fields: - self.assertFalse(self._get_field_values(serial_str, field_name)) - - for field_name in valid_fields: - self.assertTrue(self._get_field_values(serial_str, field_name)) - - def test_serialize_unicode(self): - """Tests that unicode makes the roundtrip intact""" - actor_name = u"Za\u017c\u00f3\u0142\u0107" - movie_title = u'G\u0119\u015bl\u0105 ja\u017a\u0144' - ac = Actor(name=actor_name) - mv = Movie(title=movie_title, actor=ac) - ac.save() - mv.save() - - serial_str = serializers.serialize(self.serializer_name, [mv]) - self.assertEqual(self._get_field_values(serial_str, "title")[0], movie_title) - self.assertEqual(self._get_field_values(serial_str, "actor")[0], actor_name) - - obj_list = list(serializers.deserialize(self.serializer_name, serial_str)) - mv_obj = obj_list[0].object - self.assertEqual(mv_obj.title, movie_title) - - def test_serialize_with_null_pk(self): - """ - Tests that serialized data with no primary key results - in a model instance with no id - """ - category = Category(name="Reference") - serial_str = serializers.serialize(self.serializer_name, [category]) - pk_value = self._get_pk_values(serial_str)[0] - self.assertFalse(pk_value) - - cat_obj = list(serializers.deserialize(self.serializer_name, - serial_str))[0].object - self.assertEqual(cat_obj.id, None) - - def test_float_serialization(self): - """Tests that float values serialize and deserialize intact""" - sc = Score(score=3.4) - sc.save() - serial_str = serializers.serialize(self.serializer_name, [sc]) - deserial_objs = list(serializers.deserialize(self.serializer_name, - serial_str)) - self.assertEqual(deserial_objs[0].object.score, Approximate(3.4, places=1)) - - def test_custom_field_serialization(self): - """Tests that custom fields serialize and deserialize intact""" - team_str = "Spartak Moskva" - player = Player() - player.name = "Soslan Djanaev" - player.rank = 1 - player.team = Team(team_str) - player.save() - serial_str = serializers.serialize(self.serializer_name, - Player.objects.all()) - team = self._get_field_values(serial_str, "team") - self.assertTrue(team) - self.assertEqual(team[0], team_str) - - deserial_objs = list(serializers.deserialize(self.serializer_name, serial_str)) - self.assertEqual(deserial_objs[0].object.team.to_string(), - player.team.to_string()) - - def test_pre_1000ad_date(self): - """Tests that year values before 1000AD are properly formatted""" - # Regression for #12524 -- dates before 1000AD get prefixed - # 0's on the year - a = Article.objects.create( - author = self.jane, - headline = "Nobody remembers the early years", - pub_date = datetime(1, 2, 3, 4, 5, 6)) - - serial_str = serializers.serialize(self.serializer_name, [a]) - date_values = self._get_field_values(serial_str, "pub_date") - self.assertEquals(date_values[0], "0001-02-03 04:05:06") - - def test_pkless_serialized_strings(self): - """ - Tests that serialized strings without PKs - can be turned into models - """ - deserial_objs = list(serializers.deserialize(self.serializer_name, - self.pkless_str)) - for obj in deserial_objs: - self.assertFalse(obj.object.id) - obj.save() - self.assertEqual(Category.objects.all().count(), 4) - - -class SerializersTransactionTestBase(object): - def test_forward_refs(self): - """ - Tests that objects ids can be referenced before they are - defined in the serialization data. - """ - # The deserialization process needs to be contained - # within a transaction in order to test forward reference - # handling. - transaction.enter_transaction_management() - transaction.managed(True) - objs = serializers.deserialize(self.serializer_name, self.fwd_ref_str) - for obj in objs: - obj.save() - transaction.commit() - transaction.leave_transaction_management() - - for model_cls in (Category, Author, Article): - self.assertEqual(model_cls.objects.all().count(), 1) - art_obj = Article.objects.all()[0] - self.assertEqual(art_obj.categories.all().count(), 1) - self.assertEqual(art_obj.author.name, "Agnes") - - -class XmlSerializerTestCase(SerializersTestBase, TestCase): - serializer_name = "xml" - pkless_str = """<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object model="serializers.category"> - <field type="CharField" name="name">Reference</field> - </object> -</django-objects>""" - - @staticmethod - def _comparison_value(value): - # The XML serializer handles everything as strings, so comparisons - # need to be performed on the stringified value - return unicode(value) - - @staticmethod - def _validate_output(serial_str): - try: - minidom.parseString(serial_str) - except Exception: - return False - else: - return True - - @staticmethod - def _get_pk_values(serial_str): - ret_list = [] - dom = minidom.parseString(serial_str) - fields = dom.getElementsByTagName("object") - for field in fields: - ret_list.append(field.getAttribute("pk")) - return ret_list - - @staticmethod - def _get_field_values(serial_str, field_name): - ret_list = [] - dom = minidom.parseString(serial_str) - fields = dom.getElementsByTagName("field") - for field in fields: - if field.getAttribute("name") == field_name: - temp = [] - for child in field.childNodes: - temp.append(child.nodeValue) - ret_list.append("".join(temp)) - return ret_list - -class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): - serializer_name = "xml" - fwd_ref_str = """<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - <object pk="1" model="serializers.article"> - <field to="serializers.author" name="author" rel="ManyToOneRel">1</field> - <field type="CharField" name="headline">Forward references pose no problem</field> - <field type="DateTimeField" name="pub_date">2006-06-16 15:00:00</field> - <field to="serializers.category" name="categories" rel="ManyToManyRel"> - <object pk="1"></object> - </field> - </object> - <object pk="1" model="serializers.author"> - <field type="CharField" name="name">Agnes</field> - </object> - <object pk="1" model="serializers.category"> - <field type="CharField" name="name">Reference</field></object> -</django-objects>""" - - -class JsonSerializerTestCase(SerializersTestBase, TestCase): - serializer_name = "json" - pkless_str = """[{"pk": null, "model": "serializers.category", "fields": {"name": "Reference"}}]""" - - @staticmethod - def _validate_output(serial_str): - try: - simplejson.loads(serial_str) - except Exception: - return False - else: - return True - - @staticmethod - def _get_pk_values(serial_str): - ret_list = [] - serial_list = simplejson.loads(serial_str) - for obj_dict in serial_list: - ret_list.append(obj_dict["pk"]) - return ret_list - - @staticmethod - def _get_field_values(serial_str, field_name): - ret_list = [] - serial_list = simplejson.loads(serial_str) - for obj_dict in serial_list: - if field_name in obj_dict["fields"]: - ret_list.append(obj_dict["fields"][field_name]) - return ret_list - -class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): - serializer_name = "json" - fwd_ref_str = """[ - { - "pk": 1, - "model": "serializers.article", - "fields": { - "headline": "Forward references pose no problem", - "pub_date": "2006-06-16 15:00:00", - "categories": [1], - "author": 1 - } - }, - { - "pk": 1, - "model": "serializers.category", - "fields": { - "name": "Reference" - } - }, - { - "pk": 1, - "model": "serializers.author", - "fields": { - "name": "Agnes" - } - }]""" - -try: - import yaml -except ImportError: - pass -else: - class YamlSerializerTestCase(SerializersTestBase, TestCase): - serializer_name = "yaml" - fwd_ref_str = """- fields: - headline: Forward references pose no problem - pub_date: 2006-06-16 15:00:00 - categories: [1] - author: 1 - pk: 1 - model: serializers.article -- fields: - name: Reference - pk: 1 - model: serializers.category -- fields: - name: Agnes - pk: 1 - model: serializers.author""" - - pkless_str = """- fields: - name: Reference - pk: null - model: serializers.category""" - - @staticmethod - def _validate_output(serial_str): - try: - yaml.load(StringIO(serial_str)) - except Exception: - return False - else: - return True - - @staticmethod - def _get_pk_values(serial_str): - ret_list = [] - stream = StringIO(serial_str) - for obj_dict in yaml.load(stream): - ret_list.append(obj_dict["pk"]) - return ret_list - - @staticmethod - def _get_field_values(serial_str, field_name): - ret_list = [] - stream = StringIO(serial_str) - for obj_dict in yaml.load(stream): - if "fields" in obj_dict and field_name in obj_dict["fields"]: - field_value = obj_dict["fields"][field_name] - # yaml.load will return non-string objects for some - # of the fields we are interested in, this ensures that - # everything comes back as a string - if isinstance(field_value, basestring): - ret_list.append(field_value) - else: - ret_list.append(str(field_value)) - return ret_list - - class YamlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): - serializer_name = "yaml" - fwd_ref_str = """- fields: - headline: Forward references pose no problem - pub_date: 2006-06-16 15:00:00 - categories: [1] - author: 1 - pk: 1 - model: serializers.article -- fields: - name: Reference - pk: 1 - model: serializers.category -- fields: - name: Agnes - pk: 1 - model: serializers.author""" diff --git a/parts/django/tests/modeltests/signals/__init__.py b/parts/django/tests/modeltests/signals/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/signals/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/signals/models.py b/parts/django/tests/modeltests/signals/models.py deleted file mode 100644 index f1250b4..0000000 --- a/parts/django/tests/modeltests/signals/models.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -Testing signals before/after saving and deleting. -""" - -from django.db import models - - -class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=20) - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name) diff --git a/parts/django/tests/modeltests/signals/tests.py b/parts/django/tests/modeltests/signals/tests.py deleted file mode 100644 index 27948c6..0000000 --- a/parts/django/tests/modeltests/signals/tests.py +++ /dev/null @@ -1,148 +0,0 @@ -from django.db.models import signals -from django.test import TestCase - -from models import Person - - -# #8285: signals can be any callable -class PostDeleteHandler(object): - def __init__(self, data): - self.data = data - - def __call__(self, signal, sender, instance, **kwargs): - self.data.append( - (instance, instance.id is None) - ) - -class MyReceiver(object): - def __init__(self, param): - self.param = param - self._run = False - - def __call__(self, signal, sender, **kwargs): - self._run = True - signal.disconnect(receiver=self, sender=sender) - -class SignalTests(TestCase): - def test_basic(self): - # Save up the number of connected signals so that we can check at the - # end that all the signals we register get properly unregistered (#9989) - pre_signals = ( - len(signals.pre_save.receivers), - len(signals.post_save.receivers), - len(signals.pre_delete.receivers), - len(signals.post_delete.receivers), - ) - - data = [] - - def pre_save_test(signal, sender, instance, **kwargs): - data.append( - (instance, kwargs.get("raw", False)) - ) - signals.pre_save.connect(pre_save_test) - - def post_save_test(signal, sender, instance, **kwargs): - data.append( - (instance, kwargs.get("created"), kwargs.get("raw", False)) - ) - signals.post_save.connect(post_save_test) - - def pre_delete_test(signal, sender, instance, **kwargs): - data.append( - (instance, instance.id is None) - ) - signals.pre_delete.connect(pre_delete_test) - - post_delete_test = PostDeleteHandler(data) - signals.post_delete.connect(post_delete_test) - - p1 = Person(first_name="John", last_name="Smith") - self.assertEqual(data, []) - p1.save() - self.assertEqual(data, [ - (p1, False), - (p1, True, False), - ]) - data[:] = [] - - p1.first_name = "Tom" - p1.save() - self.assertEqual(data, [ - (p1, False), - (p1, False, False), - ]) - data[:] = [] - - # Calling an internal method purely so that we can trigger a "raw" save. - p1.save_base(raw=True) - self.assertEqual(data, [ - (p1, True), - (p1, False, True), - ]) - data[:] = [] - - p1.delete() - self.assertEqual(data, [ - (p1, False), - (p1, False), - ]) - data[:] = [] - - p2 = Person(first_name="James", last_name="Jones") - p2.id = 99999 - p2.save() - self.assertEqual(data, [ - (p2, False), - (p2, True, False), - ]) - data[:] = [] - - p2.id = 99998 - p2.save() - self.assertEqual(data, [ - (p2, False), - (p2, True, False), - ]) - data[:] = [] - - p2.delete() - self.assertEqual(data, [ - (p2, False), - (p2, False) - ]) - - self.assertQuerysetEqual( - Person.objects.all(), [ - "James Jones", - ], - unicode - ) - - signals.post_delete.disconnect(post_delete_test) - signals.pre_delete.disconnect(pre_delete_test) - signals.post_save.disconnect(post_save_test) - signals.pre_save.disconnect(pre_save_test) - - # Check that all our signals got disconnected properly. - post_signals = ( - len(signals.pre_save.receivers), - len(signals.post_save.receivers), - len(signals.pre_delete.receivers), - len(signals.post_delete.receivers), - ) - self.assertEqual(pre_signals, post_signals) - - def test_disconnect_in_dispatch(self): - """ - Test that signals that disconnect when being called don't mess future - dispatching. - """ - a, b = MyReceiver(1), MyReceiver(2) - signals.post_save.connect(sender=Person, receiver=a) - signals.post_save.connect(sender=Person, receiver=b) - p = Person.objects.create(first_name='John', last_name='Smith') - - self.assertTrue(a._run) - self.assertTrue(b._run) - self.assertEqual(signals.post_save.receivers, []) diff --git a/parts/django/tests/modeltests/str/__init__.py b/parts/django/tests/modeltests/str/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/str/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/str/models.py b/parts/django/tests/modeltests/str/models.py deleted file mode 100644 index 84b8d67..0000000 --- a/parts/django/tests/modeltests/str/models.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -""" -2. Adding __str__() or __unicode__() to models - -Although it's not a strict requirement, each model should have a -``_str__()`` or ``__unicode__()`` method to return a "human-readable" -representation of the object. Do this not only for your own sanity when dealing -with the interactive prompt, but also because objects' representations are used -throughout Django's automatically-generated admin. - -Normally, you should write ``__unicode__()`` method, since this will work for -all field types (and Django will automatically provide an appropriate -``__str__()`` method). However, you can write a ``__str__()`` method directly, -if you prefer. You must be careful to encode the results correctly, though. -""" - -from django.db import models - -class Article(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateTimeField() - - def __str__(self): - # Caution: this is only safe if you are certain that headline will be - # in ASCII. - return self.headline - -class InternationalArticle(models.Model): - headline = models.CharField(max_length=100) - pub_date = models.DateTimeField() - - def __unicode__(self): - return self.headline
\ No newline at end of file diff --git a/parts/django/tests/modeltests/str/tests.py b/parts/django/tests/modeltests/str/tests.py deleted file mode 100644 index 4e4c765..0000000 --- a/parts/django/tests/modeltests/str/tests.py +++ /dev/null @@ -1,23 +0,0 @@ - # -*- coding: utf-8 -*- -import datetime - -from django.test import TestCase - -from models import Article, InternationalArticle - -class SimpleTests(TestCase): - def test_basic(self): - a = Article.objects.create( - headline='Area man programs in Python', - pub_date=datetime.datetime(2005, 7, 28) - ) - self.assertEqual(str(a), 'Area man programs in Python') - self.assertEqual(repr(a), '<Article: Area man programs in Python>') - - def test_international(self): - a = InternationalArticle.objects.create( - headline=u'Girl wins €12.500 in lottery', - pub_date=datetime.datetime(2005, 7, 28) - ) - # The default str() output will be the UTF-8 encoded output of __unicode__(). - self.assertEqual(str(a), 'Girl wins \xe2\x82\xac12.500 in lottery')
\ No newline at end of file diff --git a/parts/django/tests/modeltests/test_client/__init__.py b/parts/django/tests/modeltests/test_client/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/test_client/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/test_client/fixtures/testdata.json b/parts/django/tests/modeltests/test_client/fixtures/testdata.json deleted file mode 100644 index 0dcf625..0000000 --- a/parts/django/tests/modeltests/test_client/fixtures/testdata.json +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "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": "2", - "model": "auth.user", - "fields": { - "username": "inactive", - "first_name": "Inactive", - "last_name": "User", - "is_active": false, - "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": "3", - "model": "auth.user", - "fields": { - "username": "staff", - "first_name": "Staff", - "last_name": "Member", - "is_active": true, - "is_superuser": false, - "is_staff": true, - "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" - } - } -]
\ No newline at end of file diff --git a/parts/django/tests/modeltests/test_client/models.py b/parts/django/tests/modeltests/test_client/models.py deleted file mode 100644 index 654f649..0000000 --- a/parts/django/tests/modeltests/test_client/models.py +++ /dev/null @@ -1,459 +0,0 @@ -# coding: utf-8 -""" -39. Testing using the Test Client - -The test client is a class that can act like a simple -browser for testing purposes. - -It allows the user to compose GET and POST requests, and -obtain the response that the server gave to those requests. -The server Response objects are annotated with the details -of the contexts and templates that were rendered during the -process of serving the request. - -``Client`` objects are stateful - they will retain cookie (and -thus session) details for the lifetime of the ``Client`` instance. - -This is not intended as a replacement for Twill, Selenium, or -other browser automation frameworks - it is here to allow -testing against the contexts and templates produced by a view, -rather than the HTML rendered to the end-user. - -""" -from django.test import Client, TestCase -from django.conf import settings -from django.core import mail - -class ClientTest(TestCase): - fixtures = ['testdata.json'] - - def test_get_view(self): - "GET a view" - # The data is ignored, but let's check it doesn't crash the system - # anyway. - data = {'var': u'\xf2'} - response = self.client.get('/test_client/get_view/', data) - - # Check some response details - self.assertContains(response, 'This is a test') - self.assertEqual(response.context['var'], u'\xf2') - self.assertEqual(response.template.name, 'GET Template') - - def test_get_post_view(self): - "GET a view that normally expects POSTs" - response = self.client.get('/test_client/post_view/', {}) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.template.name, 'Empty GET Template') - self.assertTemplateUsed(response, 'Empty GET Template') - self.assertTemplateNotUsed(response, 'Empty POST Template') - - def test_empty_post(self): - "POST an empty dictionary to a view" - response = self.client.post('/test_client/post_view/', {}) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.template.name, 'Empty POST Template') - self.assertTemplateNotUsed(response, 'Empty GET Template') - self.assertTemplateUsed(response, 'Empty POST Template') - - def test_post(self): - "POST some data to a view" - post_data = { - 'value': 37 - } - response = self.client.post('/test_client/post_view/', post_data) - - # Check some response details - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['data'], '37') - self.assertEqual(response.template.name, 'POST Template') - self.assertTrue('Data received' in response.content) - - def test_response_headers(self): - "Check the value of HTTP headers returned in a response" - response = self.client.get("/test_client/header_view/") - - self.assertEquals(response['X-DJANGO-TEST'], 'Slartibartfast') - - def test_raw_post(self): - "POST raw data (with a content type) to a view" - test_doc = """<?xml version="1.0" encoding="utf-8"?><library><book><title>Blink</title><author>Malcolm Gladwell</author></book></library>""" - response = self.client.post("/test_client/raw_post_view/", test_doc, - content_type="text/xml") - self.assertEqual(response.status_code, 200) - self.assertEqual(response.template.name, "Book template") - self.assertEqual(response.content, "Blink - Malcolm Gladwell") - - def test_redirect(self): - "GET a URL that redirects elsewhere" - response = self.client.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) and that - # assertRedirect() understands to put an implicit http://testserver/ in - # front of non-absolute URLs. - self.assertRedirects(response, '/test_client/get_view/') - - host = 'django.testserver' - client_providing_host = Client(HTTP_HOST=host) - response = client_providing_host.get('/test_client/redirect_view/') - # Check that the response was a 302 (redirect) with absolute URI - self.assertRedirects(response, '/test_client/get_view/', host=host) - - def test_redirect_with_query(self): - "GET a URL that redirects with given GET parameters" - response = self.client.get('/test_client/redirect_view/', {'var': 'value'}) - - # Check if parameters are intact - self.assertRedirects(response, 'http://testserver/test_client/get_view/?var=value') - - def test_permanent_redirect(self): - "GET a URL that redirects permanently elsewhere" - response = self.client.get('/test_client/permanent_redirect_view/') - # Check that the response was a 301 (permanent redirect) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=301) - - client_providing_host = Client(HTTP_HOST='django.testserver') - response = client_providing_host.get('/test_client/permanent_redirect_view/') - # Check that the response was a 301 (permanent redirect) with absolute URI - self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) - - def test_temporary_redirect(self): - "GET a URL that does a non-permanent redirect" - response = self.client.get('/test_client/temporary_redirect_view/') - # Check that the response was a 302 (non-permanent redirect) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302) - - def test_redirect_to_strange_location(self): - "GET a URL that redirects to a non-200 page" - response = self.client.get('/test_client/double_redirect_view/') - - # Check that the response was a 302, and that - # the attempt to get the redirection location returned 301 when retrieved - self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', target_status_code=301) - - def test_follow_redirect(self): - "A URL that redirects can be followed to termination." - response = self.client.get('/test_client/double_redirect_view/', follow=True) - self.assertRedirects(response, 'http://testserver/test_client/get_view/', status_code=302, target_status_code=200) - self.assertEquals(len(response.redirect_chain), 2) - - def test_redirect_http(self): - "GET a URL that redirects to an http URI" - response = self.client.get('/test_client/http_redirect_view/',follow=True) - self.assertFalse(response.test_was_secure_request) - - def test_redirect_https(self): - "GET a URL that redirects to an https URI" - response = self.client.get('/test_client/https_redirect_view/',follow=True) - self.assertTrue(response.test_was_secure_request) - - def test_notfound_response(self): - "GET a URL that responds as '404:Not Found'" - response = self.client.get('/test_client/bad_view/') - - # Check that the response was a 404, and that the content contains MAGIC - self.assertContains(response, 'MAGIC', status_code=404) - - def test_valid_form(self): - "POST valid data to a form" - post_data = { - 'text': 'Hello World', - 'email': 'foo@example.com', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Valid POST Template") - - def test_valid_form_with_hints(self): - "GET a form, providing hints in the GET data" - hints = { - 'text': 'Hello World', - 'multi': ('b','c','e') - } - response = self.client.get('/test_client/form_view/', data=hints) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Form GET Template") - # Check that the multi-value data has been rolled out ok - self.assertContains(response, 'Select a valid choice.', 0) - - def test_incomplete_data_form(self): - "POST incomplete data to a form" - post_data = { - 'text': 'Hello World', - 'value': 37 - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertContains(response, 'This field is required.', 3) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'This field is required.') - self.assertFormError(response, 'form', 'single', 'This field is required.') - self.assertFormError(response, 'form', 'multi', 'This field is required.') - - def test_form_error(self): - "POST erroneous data to a form" - post_data = { - 'text': 'Hello World', - 'email': 'not an email address', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view/', post_data) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'Enter a valid e-mail address.') - - def test_valid_form_with_template(self): - "POST valid data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'email': 'foo@example.com', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data OK') - self.assertTemplateUsed(response, "form_view.html") - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Valid POST Template") - - def test_incomplete_data_form_with_template(self): - "POST incomplete data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'value': 37 - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data has errors') - self.assertTemplateUsed(response, 'form_view.html') - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'This field is required.') - self.assertFormError(response, 'form', 'single', 'This field is required.') - self.assertFormError(response, 'form', 'multi', 'This field is required.') - - def test_form_error_with_template(self): - "POST erroneous data to a form using multiple templates" - post_data = { - 'text': 'Hello World', - 'email': 'not an email address', - 'value': 37, - 'single': 'b', - 'multi': ('b','c','e') - } - response = self.client.post('/test_client/form_view_with_template/', post_data) - self.assertContains(response, 'POST data has errors') - self.assertTemplateUsed(response, "form_view.html") - self.assertTemplateUsed(response, 'base.html') - self.assertTemplateNotUsed(response, "Invalid POST Template") - - self.assertFormError(response, 'form', 'email', 'Enter a valid e-mail address.') - - def test_unknown_page(self): - "GET an invalid URL" - response = self.client.get('/test_client/unknown_view/') - - # Check that the response was a 404 - self.assertEqual(response.status_code, 404) - - def test_view_with_login(self): - "Request a page that is protected with @login_required" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_method_login(self): - "Request a page that is protected with a @login_required method" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_method_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_method_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_login_and_custom_redirect(self): - "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/login_protected_view_custom_redirect/') - self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view_custom_redirect/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - def test_view_with_bad_login(self): - "Request a page that is protected with @login, but use bad credentials" - - login = self.client.login(username='otheruser', password='nopassword') - self.assertFalse(login) - - def test_view_with_inactive_login(self): - "Request a page that is protected with @login, but use an inactive login" - - login = self.client.login(username='inactive', password='password') - self.assertFalse(login) - - def test_logout(self): - "Request a logout after logging in" - # Log in - self.client.login(username='testclient', password='password') - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertEqual(response.status_code, 200) - self.assertEqual(response.context['user'].username, 'testclient') - - # Log out - self.client.logout() - - # Request a page that requires a login - response = self.client.get('/test_client/login_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/login_protected_view/') - - def test_view_with_permissions(self): - "Request a page that is protected with @permission_required" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/permission_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Log in with wrong permissions. Should result in 302. - response = self.client.get('/test_client/permission_protected_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_view/') - - # TODO: Log in with right permissions and request the page again - - def test_view_with_method_permissions(self): - "Request a page that is protected with a @permission_required method" - - # Get the page without logging in. Should result in 302. - response = self.client.get('/test_client/permission_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') - - # Log in - login = self.client.login(username='testclient', password='password') - self.assertTrue(login, 'Could not log in') - - # Log in with wrong permissions. Should result in 302. - response = self.client.get('/test_client/permission_protected_method_view/') - self.assertRedirects(response, 'http://testserver/accounts/login/?next=/test_client/permission_protected_method_view/') - - # TODO: Log in with right permissions and request the page again - - def test_session_modifying_view(self): - "Request a page that modifies the session" - # Session value isn't set initially - try: - self.client.session['tobacconist'] - self.fail("Shouldn't have a session value") - except KeyError: - pass - - from django.contrib.sessions.models import Session - response = self.client.post('/test_client/session_view/') - - # Check that the session was modified - self.assertEquals(self.client.session['tobacconist'], 'hovercraft') - - def test_view_with_exception(self): - "Request a page that is known to throw an error" - self.assertRaises(KeyError, self.client.get, "/test_client/broken_view/") - - #Try the same assertion, a different way - try: - self.client.get('/test_client/broken_view/') - self.fail('Should raise an error') - except KeyError: - pass - - def test_mail_sending(self): - "Test that mail is redirected to a dummy outbox during test setup" - - response = self.client.get('/test_client/mail_sending_view/') - self.assertEqual(response.status_code, 200) - - self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].subject, 'Test message') - self.assertEqual(mail.outbox[0].body, 'This is a test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') - self.assertEqual(mail.outbox[0].to[0], 'first@example.com') - self.assertEqual(mail.outbox[0].to[1], 'second@example.com') - - def test_mass_mail_sending(self): - "Test that mass mail is redirected to a dummy outbox during test setup" - - response = self.client.get('/test_client/mass_mail_sending_view/') - self.assertEqual(response.status_code, 200) - - self.assertEqual(len(mail.outbox), 2) - self.assertEqual(mail.outbox[0].subject, 'First Test message') - self.assertEqual(mail.outbox[0].body, 'This is the first test email') - self.assertEqual(mail.outbox[0].from_email, 'from@example.com') - self.assertEqual(mail.outbox[0].to[0], 'first@example.com') - self.assertEqual(mail.outbox[0].to[1], 'second@example.com') - - self.assertEqual(mail.outbox[1].subject, 'Second Test message') - self.assertEqual(mail.outbox[1].body, 'This is the second test email') - self.assertEqual(mail.outbox[1].from_email, 'from@example.com') - self.assertEqual(mail.outbox[1].to[0], 'second@example.com') - self.assertEqual(mail.outbox[1].to[1], 'third@example.com') - -class CSRFEnabledClientTests(TestCase): - def setUp(self): - # Enable the CSRF middleware for this test - self.old_MIDDLEWARE_CLASSES = settings.MIDDLEWARE_CLASSES - csrf_middleware_class = 'django.middleware.csrf.CsrfViewMiddleware' - if csrf_middleware_class not in settings.MIDDLEWARE_CLASSES: - settings.MIDDLEWARE_CLASSES += (csrf_middleware_class,) - - def tearDown(self): - settings.MIDDLEWARE_CLASSES = self.old_MIDDLEWARE_CLASSES - - def test_csrf_enabled_client(self): - "A client can be instantiated with CSRF checks enabled" - csrf_client = Client(enforce_csrf_checks=True) - - # The normal client allows the post - response = self.client.post('/test_client/post_view/', {}) - self.assertEqual(response.status_code, 200) - - # The CSRF-enabled client rejects it - response = csrf_client.post('/test_client/post_view/', {}) - self.assertEqual(response.status_code, 403) diff --git a/parts/django/tests/modeltests/test_client/tests.py b/parts/django/tests/modeltests/test_client/tests.py deleted file mode 100644 index 09f292e..0000000 --- a/parts/django/tests/modeltests/test_client/tests.py +++ /dev/null @@ -1,20 +0,0 @@ -# Validate that you can override the default test suite - -import unittest - -def suite(): - """ - Define a suite that deliberately ignores a test defined in - this module. - """ - - testSuite = unittest.TestSuite() - testSuite.addTest(SampleTests('testGoodStuff')) - return testSuite - -class SampleTests(unittest.TestCase): - def testGoodStuff(self): - pass - - def testBadStuff(self): - self.fail("This test shouldn't run") diff --git a/parts/django/tests/modeltests/test_client/urls.py b/parts/django/tests/modeltests/test_client/urls.py deleted file mode 100644 index 9e0eabe..0000000 --- a/parts/django/tests/modeltests/test_client/urls.py +++ /dev/null @@ -1,29 +0,0 @@ -from django.conf.urls.defaults import * -from django.views.generic.simple import redirect_to -import views - -urlpatterns = patterns('', - (r'^get_view/$', views.get_view), - (r'^post_view/$', views.post_view), - (r'^header_view/$', views.view_with_header), - (r'^raw_post_view/$', views.raw_post_view), - (r'^redirect_view/$', views.redirect_view), - (r'^secure_view/$', views.view_with_secure), - (r'^permanent_redirect_view/$', redirect_to, {'url': '/test_client/get_view/'}), - (r'^temporary_redirect_view/$', redirect_to, {'url': '/test_client/get_view/', 'permanent': False}), - (r'^http_redirect_view/$', redirect_to, {'url': '/test_client/secure_view/'}), - (r'^https_redirect_view/$', redirect_to, {'url': 'https://testserver/test_client/secure_view/'}), - (r'^double_redirect_view/$', views.double_redirect_view), - (r'^bad_view/$', views.bad_view), - (r'^form_view/$', views.form_view), - (r'^form_view_with_template/$', views.form_view_with_template), - (r'^login_protected_view/$', views.login_protected_view), - (r'^login_protected_method_view/$', views.login_protected_method_view), - (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect), - (r'^permission_protected_view/$', views.permission_protected_view), - (r'^permission_protected_method_view/$', views.permission_protected_method_view), - (r'^session_view/$', views.session_view), - (r'^broken_view/$', views.broken_view), - (r'^mail_sending_view/$', views.mail_sending_view), - (r'^mass_mail_sending_view/$', views.mass_mail_sending_view) -) diff --git a/parts/django/tests/modeltests/test_client/views.py b/parts/django/tests/modeltests/test_client/views.py deleted file mode 100644 index baa9525..0000000 --- a/parts/django/tests/modeltests/test_client/views.py +++ /dev/null @@ -1,214 +0,0 @@ -from xml.dom.minidom import parseString - -from django.core import mail -from django.template import Context, Template -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound -from django.contrib.auth.decorators import login_required, permission_required -from django.forms.forms import Form -from django.forms import fields -from django.shortcuts import render_to_response -from django.utils.decorators import method_decorator - -def get_view(request): - "A simple view that expects a GET request, and returns a rendered template" - t = Template('This is a test. {{ var }} is the value.', name='GET Template') - c = Context({'var': request.GET.get('var', 42)}) - - return HttpResponse(t.render(c)) - -def post_view(request): - """A view that expects a POST, and returns a different template depending - on whether any POST data is available - """ - if request.method == 'POST': - if request.POST: - t = Template('Data received: {{ data }} is the value.', name='POST Template') - c = Context({'data': request.POST['value']}) - else: - t = Template('Viewing POST page.', name='Empty POST Template') - c = Context() - else: - t = Template('Viewing GET page.', name='Empty GET Template') - c = Context() - - return HttpResponse(t.render(c)) - -def view_with_header(request): - "A view that has a custom header" - response = HttpResponse() - response['X-DJANGO-TEST'] = 'Slartibartfast' - return response - -def raw_post_view(request): - """A view which expects raw XML to be posted and returns content extracted - from the XML""" - if request.method == 'POST': - root = parseString(request.raw_post_data) - first_book = root.firstChild.firstChild - title, author = [n.firstChild.nodeValue for n in first_book.childNodes] - t = Template("{{ title }} - {{ author }}", name="Book template") - c = Context({"title": title, "author": author}) - else: - t = Template("GET request.", name="Book GET template") - c = Context() - - return HttpResponse(t.render(c)) - -def redirect_view(request): - "A view that redirects all requests to the GET view" - if request.GET: - from urllib import urlencode - query = '?' + urlencode(request.GET, True) - else: - query = '' - return HttpResponseRedirect('/test_client/get_view/' + query) - -def view_with_secure(request): - "A view that indicates if the request was secure" - response = HttpResponse() - response.test_was_secure_request = request.is_secure() - return response - -def double_redirect_view(request): - "A view that redirects all requests to a redirection view" - return HttpResponseRedirect('/test_client/permanent_redirect_view/') - -def bad_view(request): - "A view that returns a 404 with some error content" - return HttpResponseNotFound('Not found!. This page contains some MAGIC content') - -TestChoices = ( - ('a', 'First Choice'), - ('b', 'Second Choice'), - ('c', 'Third Choice'), - ('d', 'Fourth Choice'), - ('e', 'Fifth Choice') -) - -class TestForm(Form): - text = fields.CharField() - email = fields.EmailField() - value = fields.IntegerField() - single = fields.ChoiceField(choices=TestChoices) - multi = fields.MultipleChoiceField(choices=TestChoices) - -def form_view(request): - "A view that tests a simple form" - if request.method == 'POST': - form = TestForm(request.POST) - if form.is_valid(): - t = Template('Valid POST data.', name='Valid POST Template') - c = Context() - else: - t = Template('Invalid POST data. {{ form.errors }}', name='Invalid POST Template') - c = Context({'form': form}) - else: - form = TestForm(request.GET) - t = Template('Viewing base form. {{ form }}.', name='Form GET Template') - c = Context({'form': form}) - - return HttpResponse(t.render(c)) - -def form_view_with_template(request): - "A view that tests a simple form" - if request.method == 'POST': - form = TestForm(request.POST) - if form.is_valid(): - message = 'POST data OK' - else: - message = 'POST data has errors' - else: - form = TestForm() - message = 'GET form page' - return render_to_response('form_view.html', - { - 'form': form, - 'message': message - } - ) - -def login_protected_view(request): - "A simple view that is login protected." - t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') - c = Context({'user': request.user}) - - return HttpResponse(t.render(c)) -login_protected_view = login_required(login_protected_view) - -def login_protected_view_changed_redirect(request): - "A simple view that is login protected with a custom redirect field set" - t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') - c = Context({'user': request.user}) - - return HttpResponse(t.render(c)) -login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect) - -def permission_protected_view(request): - "A simple view that is permission protected." - t = Template('This is a permission protected test. ' - 'Username is {{ user.username }}. ' - 'Permissions are {{ user.get_all_permissions }}.' , - name='Permissions Template') - c = Context({'user': request.user}) - return HttpResponse(t.render(c)) -permission_protected_view = permission_required('modeltests.test_perm')(permission_protected_view) - -class _ViewManager(object): - @method_decorator(login_required) - def login_protected_view(self, request): - t = Template('This is a login protected test using a method. ' - 'Username is {{ user.username }}.', - name='Login Method Template') - c = Context({'user': request.user}) - return HttpResponse(t.render(c)) - - @method_decorator(permission_required('modeltests.test_perm')) - def permission_protected_view(self, request): - t = Template('This is a permission protected test using a method. ' - 'Username is {{ user.username }}. ' - 'Permissions are {{ user.get_all_permissions }}.' , - name='Permissions Template') - c = Context({'user': request.user}) - return HttpResponse(t.render(c)) - -_view_manager = _ViewManager() -login_protected_method_view = _view_manager.login_protected_view -permission_protected_method_view = _view_manager.permission_protected_view - -def session_view(request): - "A view that modifies the session" - request.session['tobacconist'] = 'hovercraft' - - t = Template('This is a view that modifies the session.', - name='Session Modifying View Template') - c = Context() - return HttpResponse(t.render(c)) - -def broken_view(request): - """A view which just raises an exception, simulating a broken view.""" - raise KeyError("Oops! Looks like you wrote some bad code.") - -def mail_sending_view(request): - mail.EmailMessage( - "Test message", - "This is a test email", - "from@example.com", - ['first@example.com', 'second@example.com']).send() - return HttpResponse("Mail sent") - -def mass_mail_sending_view(request): - m1 = mail.EmailMessage( - 'First Test message', - 'This is the first test email', - 'from@example.com', - ['first@example.com', 'second@example.com']) - m2 = mail.EmailMessage( - 'Second Test message', - 'This is the second test email', - 'from@example.com', - ['second@example.com', 'third@example.com']) - - c = mail.get_connection() - c.send_messages([m1,m2]) - - return HttpResponse("Mail sent") diff --git a/parts/django/tests/modeltests/transactions/__init__.py b/parts/django/tests/modeltests/transactions/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/transactions/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/transactions/models.py b/parts/django/tests/modeltests/transactions/models.py deleted file mode 100644 index d957fe1..0000000 --- a/parts/django/tests/modeltests/transactions/models.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -15. Transactions - -Django handles transactions in three different ways. The default is to commit -each transaction upon a write, but you can decorate a function to get -commit-on-success behavior. Alternatively, you can manage the transaction -manually. -""" - -from django.db import models, DEFAULT_DB_ALIAS - -class Reporter(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - email = models.EmailField() - - class Meta: - ordering = ('first_name', 'last_name') - - def __unicode__(self): - return u"%s %s" % (self.first_name, self.last_name)
\ No newline at end of file diff --git a/parts/django/tests/modeltests/transactions/tests.py b/parts/django/tests/modeltests/transactions/tests.py deleted file mode 100644 index 9964f5d..0000000 --- a/parts/django/tests/modeltests/transactions/tests.py +++ /dev/null @@ -1,155 +0,0 @@ -from django.test import TransactionTestCase -from django.db import connection, transaction, IntegrityError, DEFAULT_DB_ALIAS -from django.conf import settings - -from models import Reporter - -PGSQL = 'psycopg2' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] -MYSQL = 'mysql' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] - -class TransactionTests(TransactionTestCase): - - if not MYSQL: - - def create_a_reporter_then_fail(self, first, last): - a = Reporter(first_name=first, last_name=last) - a.save() - raise Exception("I meant to do that") - - def remove_a_reporter(self, first_name): - r = Reporter.objects.get(first_name="Alice") - r.delete() - - def manually_managed(self): - r = Reporter(first_name="Dirk", last_name="Gently") - r.save() - transaction.commit() - - def manually_managed_mistake(self): - r = Reporter(first_name="Edward", last_name="Woodward") - r.save() - # Oops, I forgot to commit/rollback! - - def execute_bad_sql(self): - cursor = connection.cursor() - cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');") - transaction.set_dirty() - - def test_autocommit(self): - """ - The default behavior is to autocommit after each save() action. - """ - self.assertRaises(Exception, - self.create_a_reporter_then_fail, - "Alice", "Smith" - ) - - # The object created before the exception still exists - self.assertEqual(Reporter.objects.count(), 1) - - def test_autocommit_decorator(self): - """ - The autocommit decorator works exactly the same as the default behavior. - """ - autocomitted_create_then_fail = transaction.autocommit( - self.create_a_reporter_then_fail - ) - self.assertRaises(Exception, - autocomitted_create_then_fail, - "Alice", "Smith" - ) - # Again, the object created before the exception still exists - self.assertEqual(Reporter.objects.count(), 1) - - def test_autocommit_decorator_with_using(self): - """ - The autocommit decorator also works with a using argument. - """ - autocomitted_create_then_fail = transaction.autocommit(using='default')( - self.create_a_reporter_then_fail - ) - self.assertRaises(Exception, - autocomitted_create_then_fail, - "Alice", "Smith" - ) - # Again, the object created before the exception still exists - self.assertEqual(Reporter.objects.count(), 1) - - def test_commit_on_success(self): - """ - With the commit_on_success decorator, the transaction is only committed - if the function doesn't throw an exception. - """ - committed_on_success = transaction.commit_on_success( - self.create_a_reporter_then_fail) - self.assertRaises(Exception, committed_on_success, "Dirk", "Gently") - # This time the object never got saved - self.assertEqual(Reporter.objects.count(), 0) - - def test_commit_on_success_with_using(self): - """ - The commit_on_success decorator also works with a using argument. - """ - using_committed_on_success = transaction.commit_on_success(using='default')( - self.create_a_reporter_then_fail - ) - self.assertRaises(Exception, - using_committed_on_success, - "Dirk", "Gently" - ) - # This time the object never got saved - self.assertEqual(Reporter.objects.count(), 0) - - def test_commit_on_success_succeed(self): - """ - If there aren't any exceptions, the data will get saved. - """ - Reporter.objects.create(first_name="Alice", last_name="Smith") - remove_comitted_on_success = transaction.commit_on_success( - self.remove_a_reporter - ) - remove_comitted_on_success("Alice") - self.assertEqual(list(Reporter.objects.all()), []) - - def test_manually_managed(self): - """ - You can manually manage transactions if you really want to, but you - have to remember to commit/rollback. - """ - manually_managed = transaction.commit_manually(self.manually_managed) - manually_managed() - self.assertEqual(Reporter.objects.count(), 1) - - def test_manually_managed_mistake(self): - """ - If you forget, you'll get bad errors. - """ - manually_managed_mistake = transaction.commit_manually( - self.manually_managed_mistake - ) - self.assertRaises(transaction.TransactionManagementError, - manually_managed_mistake) - - def test_manually_managed_with_using(self): - """ - The commit_manually function also works with a using argument. - """ - using_manually_managed_mistake = transaction.commit_manually(using='default')( - self.manually_managed_mistake - ) - self.assertRaises(transaction.TransactionManagementError, - using_manually_managed_mistake - ) - - if PGSQL: - - def test_bad_sql(self): - """ - Regression for #11900: If a function wrapped by commit_on_success - writes a transaction that can't be committed, that transaction should - be rolled back. The bug is only visible using the psycopg2 backend, - though the fix is generally a good idea. - """ - execute_bad_sql = transaction.commit_on_success(self.execute_bad_sql) - self.assertRaises(IntegrityError, execute_bad_sql) - transaction.rollback() diff --git a/parts/django/tests/modeltests/unmanaged_models/__init__.py b/parts/django/tests/modeltests/unmanaged_models/__init__.py deleted file mode 100644 index 139597f..0000000 --- a/parts/django/tests/modeltests/unmanaged_models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/parts/django/tests/modeltests/unmanaged_models/models.py b/parts/django/tests/modeltests/unmanaged_models/models.py deleted file mode 100644 index 0c2cf50..0000000 --- a/parts/django/tests/modeltests/unmanaged_models/models.py +++ /dev/null @@ -1,125 +0,0 @@ -""" -Models can have a ``managed`` attribute, which specifies whether the SQL code -is generated for the table on various manage.py operations. -""" - -from django.db import models - -# All of these models are creatd in the database by Django. - -class A01(models.Model): - f_a = models.CharField(max_length=10, db_index=True) - f_b = models.IntegerField() - - class Meta: - db_table = 'A01' - - def __unicode__(self): - return self.f_a - -class B01(models.Model): - fk_a = models.ForeignKey(A01) - f_a = models.CharField(max_length=10, db_index=True) - f_b = models.IntegerField() - - class Meta: - db_table = 'B01' - # 'managed' is True by default. This tests we can set it explicitly. - managed = True - - def __unicode__(self): - return self.f_a - -class C01(models.Model): - mm_a = models.ManyToManyField(A01, db_table='D01') - f_a = models.CharField(max_length=10, db_index=True) - f_b = models.IntegerField() - - class Meta: - db_table = 'C01' - - def __unicode__(self): - return self.f_a - -# All of these models use the same tables as the previous set (they are shadows -# of possibly a subset of the columns). There should be no creation errors, -# since we have told Django they aren't managed by Django. - -class A02(models.Model): - f_a = models.CharField(max_length=10, db_index=True) - - class Meta: - db_table = 'A01' - managed = False - - def __unicode__(self): - return self.f_a - -class B02(models.Model): - class Meta: - db_table = 'B01' - managed = False - - fk_a = models.ForeignKey(A02) - f_a = models.CharField(max_length=10, db_index=True) - f_b = models.IntegerField() - - def __unicode__(self): - return self.f_a - -# To re-use the many-to-many intermediate table, we need to manually set up -# things up. -class C02(models.Model): - mm_a = models.ManyToManyField(A02, through="Intermediate") - f_a = models.CharField(max_length=10, db_index=True) - f_b = models.IntegerField() - - class Meta: - db_table = 'C01' - managed = False - - def __unicode__(self): - return self.f_a - -class Intermediate(models.Model): - a02 = models.ForeignKey(A02, db_column="a01_id") - c02 = models.ForeignKey(C02, db_column="c01_id") - - class Meta: - db_table = 'D01' - managed = False - -# -# These next models test the creation (or not) of many to many join tables -# between managed and unmanaged models. A join table between two unmanaged -# models shouldn't be automatically created (see #10647). -# - -# Firstly, we need some models that will create the tables, purely so that the -# tables are created. This is a test setup, not a requirement for unmanaged -# models. -class Proxy1(models.Model): - class Meta: - db_table = "unmanaged_models_proxy1" - -class Proxy2(models.Model): - class Meta: - db_table = "unmanaged_models_proxy2" - -class Unmanaged1(models.Model): - class Meta: - managed = False - db_table = "unmanaged_models_proxy1" - -# Unmanged with an m2m to unmanaged: the intermediary table won't be created. -class Unmanaged2(models.Model): - mm = models.ManyToManyField(Unmanaged1) - - class Meta: - managed = False - db_table = "unmanaged_models_proxy2" - -# Here's an unmanaged model with an m2m to a managed one; the intermediary -# table *will* be created (unless given a custom `through` as for C02 above). -class Managed1(models.Model): - mm = models.ManyToManyField(Unmanaged1) diff --git a/parts/django/tests/modeltests/unmanaged_models/tests.py b/parts/django/tests/modeltests/unmanaged_models/tests.py deleted file mode 100644 index dbbe848..0000000 --- a/parts/django/tests/modeltests/unmanaged_models/tests.py +++ /dev/null @@ -1,58 +0,0 @@ -from django.test import TestCase -from django.db import connection -from models import Unmanaged1, Unmanaged2, Managed1 -from models import A01, A02, B01, B02, C01, C02 - -class SimpleTests(TestCase): - - def test_simple(self): - """ - The main test here is that the all the models can be created without - any database errors. We can also do some more simple insertion and - lookup tests whilst we're here to show that the second of models do - refer to the tables from the first set. - """ - # Insert some data into one set of models. - a = A01.objects.create(f_a="foo", f_b=42) - B01.objects.create(fk_a=a, f_a="fred", f_b=1729) - c = C01.objects.create(f_a="barney", f_b=1) - c.mm_a = [a] - - # ... and pull it out via the other set. - a2 = A02.objects.all()[0] - self.assertTrue(isinstance(a2, A02)) - self.assertEqual(a2.f_a, "foo") - - b2 = B02.objects.all()[0] - self.assertTrue(isinstance(b2, B02)) - self.assertEqual(b2.f_a, "fred") - - self.assertTrue(isinstance(b2.fk_a, A02)) - self.assertEqual(b2.fk_a.f_a, "foo") - - self.assertEqual(list(C02.objects.filter(f_a=None)), []) - - resp = list(C02.objects.filter(mm_a=a.id)) - self.assertEqual(len(resp), 1) - - self.assertTrue(isinstance(resp[0], C02)) - self.assertEqual(resp[0].f_a, 'barney') - - -class ManyToManyUnmanagedTests(TestCase): - - def test_many_to_many_between_unmanaged(self): - """ - The intermediary table between two unmanaged models should not be created. - """ - table = Unmanaged2._meta.get_field('mm').m2m_db_table() - tables = connection.introspection.table_names() - self.assert_(table not in tables, "Table '%s' should not exist, but it does." % table) - - def test_many_to_many_between_unmanaged_and_managed(self): - """ - An intermediary table between a managed and an unmanaged model should be created. - """ - table = Managed1._meta.get_field('mm').m2m_db_table() - tables = connection.introspection.table_names() - self.assert_(table in tables, "Table '%s' does not exist." % table) diff --git a/parts/django/tests/modeltests/update/__init__.py b/parts/django/tests/modeltests/update/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/update/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/update/models.py b/parts/django/tests/modeltests/update/models.py deleted file mode 100644 index 7b633e2..0000000 --- a/parts/django/tests/modeltests/update/models.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Tests for the update() queryset method that allows in-place, multi-object -updates. -""" - -from django.db import models - -class DataPoint(models.Model): - name = models.CharField(max_length=20) - value = models.CharField(max_length=20) - another_value = models.CharField(max_length=20, blank=True) - - def __unicode__(self): - return unicode(self.name) - -class RelatedPoint(models.Model): - name = models.CharField(max_length=20) - data = models.ForeignKey(DataPoint) - - def __unicode__(self): - return unicode(self.name) - - -class A(models.Model): - x = models.IntegerField(default=10) - -class B(models.Model): - a = models.ForeignKey(A) - y = models.IntegerField(default=10) - -class C(models.Model): - y = models.IntegerField(default=10) - -class D(C): - a = models.ForeignKey(A) diff --git a/parts/django/tests/modeltests/update/tests.py b/parts/django/tests/modeltests/update/tests.py deleted file mode 100644 index d0b6ea3..0000000 --- a/parts/django/tests/modeltests/update/tests.py +++ /dev/null @@ -1,116 +0,0 @@ -from django.test import TestCase - -from models import A, B, C, D, DataPoint, RelatedPoint - - -class SimpleTest(TestCase): - def setUp(self): - self.a1 = A.objects.create() - self.a2 = A.objects.create() - for x in range(20): - B.objects.create(a=self.a1) - D.objects.create(a=self.a1) - - def test_nonempty_update(self): - """ - Test that update changes the right number of rows for a nonempty queryset - """ - num_updated = self.a1.b_set.update(y=100) - self.assertEqual(num_updated, 20) - cnt = B.objects.filter(y=100).count() - self.assertEqual(cnt, 20) - - def test_empty_update(self): - """ - Test that update changes the right number of rows for an empty queryset - """ - num_updated = self.a2.b_set.update(y=100) - self.assertEqual(num_updated, 0) - cnt = B.objects.filter(y=100).count() - self.assertEqual(cnt, 0) - - def test_nonempty_update_with_inheritance(self): - """ - Test that update changes the right number of rows for an empty queryset - when the update affects only a base table - """ - num_updated = self.a1.d_set.update(y=100) - self.assertEqual(num_updated, 20) - cnt = D.objects.filter(y=100).count() - self.assertEqual(cnt, 20) - - def test_empty_update_with_inheritance(self): - """ - Test that update changes the right number of rows for an empty queryset - when the update affects only a base table - """ - num_updated = self.a2.d_set.update(y=100) - self.assertEqual(num_updated, 0) - cnt = D.objects.filter(y=100).count() - self.assertEqual(cnt, 0) - -class AdvancedTests(TestCase): - - def setUp(self): - self.d0 = DataPoint.objects.create(name="d0", value="apple") - self.d2 = DataPoint.objects.create(name="d2", value="banana") - self.d3 = DataPoint.objects.create(name="d3", value="banana") - self.r1 = RelatedPoint.objects.create(name="r1", data=self.d3) - - def test_update(self): - """ - Objects are updated by first filtering the candidates into a queryset - and then calling the update() method. It executes immediately and - returns nothing. - """ - resp = DataPoint.objects.filter(value="apple").update(name="d1") - self.assertEqual(resp, 1) - resp = DataPoint.objects.filter(value="apple") - self.assertEqual(list(resp), [self.d0]) - - def test_update_multiple_objects(self): - """ - We can update multiple objects at once. - """ - resp = DataPoint.objects.filter(value="banana").update( - value="pineapple") - self.assertEqual(resp, 2) - self.assertEqual(DataPoint.objects.get(name="d2").value, u'pineapple') - - def test_update_fk(self): - """ - Foreign key fields can also be updated, although you can only update - the object referred to, not anything inside the related object. - """ - resp = RelatedPoint.objects.filter(name="r1").update(data=self.d0) - self.assertEqual(resp, 1) - resp = RelatedPoint.objects.filter(data__name="d0") - self.assertEqual(list(resp), [self.r1]) - - def test_update_multiple_fields(self): - """ - Multiple fields can be updated at once - """ - resp = DataPoint.objects.filter(value="apple").update( - value="fruit", another_value="peach") - self.assertEqual(resp, 1) - d = DataPoint.objects.get(name="d0") - self.assertEqual(d.value, u'fruit') - self.assertEqual(d.another_value, u'peach') - - def test_update_all(self): - """ - In the rare case you want to update every instance of a model, update() - is also a manager method. - """ - self.assertEqual(DataPoint.objects.update(value='thing'), 3) - resp = DataPoint.objects.values('value').distinct() - self.assertEqual(list(resp), [{'value': u'thing'}]) - - def test_update_slice_fail(self): - """ - We do not support update on already sliced query sets. - """ - method = DataPoint.objects.all()[:2].update - self.assertRaises(AssertionError, method, - another_value='another thing') diff --git a/parts/django/tests/modeltests/user_commands/__init__.py b/parts/django/tests/modeltests/user_commands/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/user_commands/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/user_commands/management/__init__.py b/parts/django/tests/modeltests/user_commands/management/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/user_commands/management/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/user_commands/management/commands/__init__.py b/parts/django/tests/modeltests/user_commands/management/commands/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/user_commands/management/commands/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/user_commands/management/commands/dance.py b/parts/django/tests/modeltests/user_commands/management/commands/dance.py deleted file mode 100644 index acefe09..0000000 --- a/parts/django/tests/modeltests/user_commands/management/commands/dance.py +++ /dev/null @@ -1,14 +0,0 @@ -from optparse import make_option -from django.core.management.base import BaseCommand - -class Command(BaseCommand): - help = "Dance around like a madman." - args = '' - requires_model_validation = True - - option_list =[ - make_option("-s", "--style", default="Rock'n'Roll") - ] - - def handle(self, *args, **options): - self.stdout.write("I don't feel like dancing %s." % options["style"]) diff --git a/parts/django/tests/modeltests/user_commands/models.py b/parts/django/tests/modeltests/user_commands/models.py deleted file mode 100644 index f2aa549..0000000 --- a/parts/django/tests/modeltests/user_commands/models.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -38. User-registered management commands - -The ``manage.py`` utility provides a number of useful commands for managing a -Django project. If you want to add a utility command of your own, you can. - -The user-defined command ``dance`` is defined in the management/commands -subdirectory of this test application. It is a simple command that responds -with a printed message when invoked. - -For more details on how to define your own ``manage.py`` commands, look at the -``django.core.management.commands`` directory. This directory contains the -definitions for the base Django ``manage.py`` commands. -""" diff --git a/parts/django/tests/modeltests/user_commands/tests.py b/parts/django/tests/modeltests/user_commands/tests.py deleted file mode 100644 index 84aa7a5..0000000 --- a/parts/django/tests/modeltests/user_commands/tests.py +++ /dev/null @@ -1,21 +0,0 @@ -from StringIO import StringIO - -from django.test import TestCase -from django.core import management -from django.core.management.base import CommandError - -class CommandTests(TestCase): - def test_command(self): - out = StringIO() - management.call_command('dance', stdout=out) - self.assertEquals(out.getvalue(), - "I don't feel like dancing Rock'n'Roll.") - - def test_command_style(self): - out = StringIO() - management.call_command('dance', style='Jive', stdout=out) - self.assertEquals(out.getvalue(), - "I don't feel like dancing Jive.") - - def test_explode(self): - self.assertRaises(CommandError, management.call_command, ('explode',))
\ No newline at end of file diff --git a/parts/django/tests/modeltests/validation/__init__.py b/parts/django/tests/modeltests/validation/__init__.py deleted file mode 100644 index d0a7d19..0000000 --- a/parts/django/tests/modeltests/validation/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -from django.core.exceptions import ValidationError - -class ValidationTestCase(unittest.TestCase): - def assertFailsValidation(self, clean, failed_fields): - self.assertRaises(ValidationError, clean) - try: - clean() - except ValidationError, e: - self.assertEquals(sorted(failed_fields), sorted(e.message_dict.keys())) - - def assertFieldFailsValidationWithMessage(self, clean, field_name, message): - self.assertRaises(ValidationError, clean) - try: - clean() - except ValidationError, e: - self.assertTrue(field_name in e.message_dict) - self.assertEquals(message, e.message_dict[field_name]) - - diff --git a/parts/django/tests/modeltests/validation/models.py b/parts/django/tests/modeltests/validation/models.py deleted file mode 100644 index dd42936..0000000 --- a/parts/django/tests/modeltests/validation/models.py +++ /dev/null @@ -1,65 +0,0 @@ -from datetime import datetime -from django.core.exceptions import ValidationError -from django.db import models -from django.test import TestCase - - -def validate_answer_to_universe(value): - if value != 42: - raise ValidationError('This is not the answer to life, universe and everything!', code='not42') - -class ModelToValidate(models.Model): - name = models.CharField(max_length=100) - created = models.DateTimeField(default=datetime.now) - number = models.IntegerField(db_column='number_val') - parent = models.ForeignKey('self', blank=True, null=True, limit_choices_to={'number': 10}) - email = models.EmailField(blank=True) - url = models.URLField(blank=True) - f_with_custom_validator = models.IntegerField(blank=True, null=True, validators=[validate_answer_to_universe]) - - def clean(self): - super(ModelToValidate, self).clean() - if self.number == 11: - raise ValidationError('Invalid number supplied!') - -class UniqueFieldsModel(models.Model): - unique_charfield = models.CharField(max_length=100, unique=True) - unique_integerfield = models.IntegerField(unique=True) - non_unique_field = models.IntegerField() - -class CustomPKModel(models.Model): - my_pk_field = models.CharField(max_length=100, primary_key=True) - -class UniqueTogetherModel(models.Model): - cfield = models.CharField(max_length=100) - ifield = models.IntegerField() - efield = models.EmailField() - - class Meta: - unique_together = (('ifield', 'cfield',), ['ifield', 'efield']) - -class UniqueForDateModel(models.Model): - start_date = models.DateField() - end_date = models.DateTimeField() - count = models.IntegerField(unique_for_date="start_date", unique_for_year="end_date") - order = models.IntegerField(unique_for_month="end_date") - name = models.CharField(max_length=100) - -class CustomMessagesModel(models.Model): - other = models.IntegerField(blank=True, null=True) - number = models.IntegerField(db_column='number_val', - error_messages={'null': 'NULL', 'not42': 'AAARGH', 'not_equal': '%s != me'}, - validators=[validate_answer_to_universe] - ) - -class Author(models.Model): - name = models.CharField(max_length=100) - -class Article(models.Model): - title = models.CharField(max_length=100) - author = models.ForeignKey(Author) - pub_date = models.DateTimeField(blank=True) - - def clean(self): - if self.pub_date is None: - self.pub_date = datetime.now() diff --git a/parts/django/tests/modeltests/validation/test_custom_messages.py b/parts/django/tests/modeltests/validation/test_custom_messages.py deleted file mode 100644 index 05bb651..0000000 --- a/parts/django/tests/modeltests/validation/test_custom_messages.py +++ /dev/null @@ -1,13 +0,0 @@ -from modeltests.validation import ValidationTestCase -from models import CustomMessagesModel - - -class CustomMessagesTest(ValidationTestCase): - def test_custom_simple_validator_message(self): - cmm = CustomMessagesModel(number=12) - self.assertFieldFailsValidationWithMessage(cmm.full_clean, 'number', ['AAARGH']) - - def test_custom_null_message(self): - cmm = CustomMessagesModel() - self.assertFieldFailsValidationWithMessage(cmm.full_clean, 'number', ['NULL']) - diff --git a/parts/django/tests/modeltests/validation/test_unique.py b/parts/django/tests/modeltests/validation/test_unique.py deleted file mode 100644 index fb77c4d..0000000 --- a/parts/django/tests/modeltests/validation/test_unique.py +++ /dev/null @@ -1,85 +0,0 @@ -import unittest -import datetime -from django.conf import settings -from django.db import connection -from models import CustomPKModel, UniqueTogetherModel, UniqueFieldsModel, UniqueForDateModel, ModelToValidate - - -class GetUniqueCheckTests(unittest.TestCase): - def test_unique_fields_get_collected(self): - m = UniqueFieldsModel() - self.assertEqual( - ([(UniqueFieldsModel, ('id',)), - (UniqueFieldsModel, ('unique_charfield',)), - (UniqueFieldsModel, ('unique_integerfield',))], - []), - m._get_unique_checks() - ) - - def test_unique_together_gets_picked_up_and_converted_to_tuple(self): - m = UniqueTogetherModel() - self.assertEqual( - ([(UniqueTogetherModel, ('ifield', 'cfield',)), - (UniqueTogetherModel, ('ifield', 'efield')), - (UniqueTogetherModel, ('id',)), ], - []), - m._get_unique_checks() - ) - - def test_primary_key_is_considered_unique(self): - m = CustomPKModel() - self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks()) - - def test_unique_for_date_gets_picked_up(self): - m = UniqueForDateModel() - self.assertEqual(( - [(UniqueForDateModel, ('id',))], - [(UniqueForDateModel, 'date', 'count', 'start_date'), - (UniqueForDateModel, 'year', 'count', 'end_date'), - (UniqueForDateModel, 'month', 'order', 'end_date')] - ), m._get_unique_checks() - ) - - def test_unique_for_date_exclusion(self): - m = UniqueForDateModel() - self.assertEqual(( - [(UniqueForDateModel, ('id',))], - [(UniqueForDateModel, 'year', 'count', 'end_date'), - (UniqueForDateModel, 'month', 'order', 'end_date')] - ), m._get_unique_checks(exclude='start_date') - ) - -class PerformUniqueChecksTest(unittest.TestCase): - def setUp(self): - # Set debug to True to gain access to connection.queries. - self._old_debug, settings.DEBUG = settings.DEBUG, True - super(PerformUniqueChecksTest, self).setUp() - - def tearDown(self): - # Restore old debug value. - settings.DEBUG = self._old_debug - super(PerformUniqueChecksTest, self).tearDown() - - def test_primary_key_unique_check_not_performed_when_adding_and_pk_not_specified(self): - # Regression test for #12560 - query_count = len(connection.queries) - mtv = ModelToValidate(number=10, name='Some Name') - setattr(mtv, '_adding', True) - mtv.full_clean() - self.assertEqual(query_count, len(connection.queries)) - - def test_primary_key_unique_check_performed_when_adding_and_pk_specified(self): - # Regression test for #12560 - query_count = len(connection.queries) - mtv = ModelToValidate(number=10, name='Some Name', id=123) - setattr(mtv, '_adding', True) - mtv.full_clean() - self.assertEqual(query_count + 1, len(connection.queries)) - - def test_primary_key_unique_check_not_performed_when_not_adding(self): - # Regression test for #12132 - query_count= len(connection.queries) - mtv = ModelToValidate(number=10, name='Some Name') - mtv.full_clean() - self.assertEqual(query_count, len(connection.queries)) - diff --git a/parts/django/tests/modeltests/validation/tests.py b/parts/django/tests/modeltests/validation/tests.py deleted file mode 100644 index 0027393..0000000 --- a/parts/django/tests/modeltests/validation/tests.py +++ /dev/null @@ -1,114 +0,0 @@ -from django import forms -from django.test import TestCase -from django.core.exceptions import NON_FIELD_ERRORS -from modeltests.validation import ValidationTestCase -from modeltests.validation.models import Author, Article, ModelToValidate - -# Import other tests for this package. -from modeltests.validation.validators import TestModelsWithValidators -from modeltests.validation.test_unique import GetUniqueCheckTests, PerformUniqueChecksTest -from modeltests.validation.test_custom_messages import CustomMessagesTest - - -class BaseModelValidationTests(ValidationTestCase): - - def test_missing_required_field_raises_error(self): - mtv = ModelToValidate(f_with_custom_validator=42) - self.assertFailsValidation(mtv.full_clean, ['name', 'number']) - - def test_with_correct_value_model_validates(self): - mtv = ModelToValidate(number=10, name='Some Name') - self.assertEqual(None, mtv.full_clean()) - - def test_custom_validate_method(self): - mtv = ModelToValidate(number=11) - self.assertFailsValidation(mtv.full_clean, [NON_FIELD_ERRORS, 'name']) - - def test_wrong_FK_value_raises_error(self): - mtv=ModelToValidate(number=10, name='Some Name', parent_id=3) - self.assertFailsValidation(mtv.full_clean, ['parent']) - - def test_correct_FK_value_validates(self): - parent = ModelToValidate.objects.create(number=10, name='Some Name') - mtv = ModelToValidate(number=10, name='Some Name', parent_id=parent.pk) - self.assertEqual(None, mtv.full_clean()) - - def test_limitted_FK_raises_error(self): - # The limit_choices_to on the parent field says that a parent object's - # number attribute must be 10, so this should fail validation. - parent = ModelToValidate.objects.create(number=11, name='Other Name') - mtv = ModelToValidate(number=10, name='Some Name', parent_id=parent.pk) - self.assertFailsValidation(mtv.full_clean, ['parent']) - - def test_wrong_email_value_raises_error(self): - mtv = ModelToValidate(number=10, name='Some Name', email='not-an-email') - self.assertFailsValidation(mtv.full_clean, ['email']) - - def test_correct_email_value_passes(self): - mtv = ModelToValidate(number=10, name='Some Name', email='valid@email.com') - self.assertEqual(None, mtv.full_clean()) - - def test_wrong_url_value_raises_error(self): - mtv = ModelToValidate(number=10, name='Some Name', url='not a url') - self.assertFieldFailsValidationWithMessage(mtv.full_clean, 'url', [u'Enter a valid value.']) - - def test_correct_url_but_nonexisting_gives_404(self): - mtv = ModelToValidate(number=10, name='Some Name', url='http://google.com/we-love-microsoft.html') - self.assertFieldFailsValidationWithMessage(mtv.full_clean, 'url', [u'This URL appears to be a broken link.']) - - def test_correct_url_value_passes(self): - mtv = ModelToValidate(number=10, name='Some Name', url='http://www.djangoproject.com/') - self.assertEqual(None, mtv.full_clean()) # This will fail if there's no Internet connection - - def test_text_greater_that_charfields_max_length_eaises_erros(self): - mtv = ModelToValidate(number=10, name='Some Name'*100) - self.assertFailsValidation(mtv.full_clean, ['name',]) - -class ArticleForm(forms.ModelForm): - class Meta: - model = Article - exclude = ['author'] - -class ModelFormsTests(TestCase): - def setUp(self): - self.author = Author.objects.create(name='Joseph Kocherhans') - - def test_partial_validation(self): - # Make sure the "commit=False and set field values later" idiom still - # works with model validation. - data = { - 'title': 'The state of model validation', - 'pub_date': '2010-1-10 14:49:00' - } - form = ArticleForm(data) - self.assertEqual(form.errors.keys(), []) - article = form.save(commit=False) - article.author = self.author - article.save() - - def test_validation_with_empty_blank_field(self): - # Since a value for pub_date wasn't provided and the field is - # blank=True, model-validation should pass. - # Also, Article.clean() should be run, so pub_date will be filled after - # validation, so the form should save cleanly even though pub_date is - # not allowed to be null. - data = { - 'title': 'The state of model validation', - } - article = Article(author_id=self.author.id) - form = ArticleForm(data, instance=article) - self.assertEqual(form.errors.keys(), []) - self.assertNotEqual(form.instance.pub_date, None) - article = form.save() - - def test_validation_with_invalid_blank_field(self): - # Even though pub_date is set to blank=True, an invalid value was - # provided, so it should fail validation. - data = { - 'title': 'The state of model validation', - 'pub_date': 'never' - } - article = Article(author_id=self.author.id) - form = ArticleForm(data, instance=article) - self.assertEqual(form.errors.keys(), ['pub_date']) - diff --git a/parts/django/tests/modeltests/validation/validators.py b/parts/django/tests/modeltests/validation/validators.py deleted file mode 100644 index 3ad2c40..0000000 --- a/parts/django/tests/modeltests/validation/validators.py +++ /dev/null @@ -1,18 +0,0 @@ -from unittest import TestCase -from modeltests.validation import ValidationTestCase -from models import * - - -class TestModelsWithValidators(ValidationTestCase): - def test_custom_validator_passes_for_correct_value(self): - mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=42) - self.assertEqual(None, mtv.full_clean()) - - def test_custom_validator_raises_error_for_incorrect_value(self): - mtv = ModelToValidate(number=10, name='Some Name', f_with_custom_validator=12) - self.assertFailsValidation(mtv.full_clean, ['f_with_custom_validator']) - self.assertFieldFailsValidationWithMessage( - mtv.full_clean, - 'f_with_custom_validator', - [u'This is not the answer to life, universe and everything!'] - ) diff --git a/parts/django/tests/modeltests/validators/__init__.py b/parts/django/tests/modeltests/validators/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/validators/__init__.py +++ /dev/null diff --git a/parts/django/tests/modeltests/validators/models.py b/parts/django/tests/modeltests/validators/models.py deleted file mode 100644 index e69de29..0000000 --- a/parts/django/tests/modeltests/validators/models.py +++ /dev/null diff --git a/parts/django/tests/modeltests/validators/tests.py b/parts/django/tests/modeltests/validators/tests.py deleted file mode 100644 index 44ad176..0000000 --- a/parts/django/tests/modeltests/validators/tests.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -import re -import types -from unittest import TestCase -from datetime import datetime, timedelta -from django.core.exceptions import ValidationError -from django.core.validators import * - -NOW = datetime.now() - -TEST_DATA = ( - # (validator, value, expected), - (validate_integer, '42', None), - (validate_integer, '-42', None), - (validate_integer, -42, None), - (validate_integer, -42.5, None), - - (validate_integer, None, ValidationError), - (validate_integer, 'a', ValidationError), - - (validate_email, 'email@here.com', None), - (validate_email, 'weirder-email@here.and.there.com', None), - - (validate_email, None, ValidationError), - (validate_email, '', ValidationError), - (validate_email, 'abc', ValidationError), - (validate_email, 'a @x.cz', ValidationError), - (validate_email, 'something@@somewhere.com', ValidationError), - - (validate_slug, 'slug-ok', None), - (validate_slug, 'longer-slug-still-ok', None), - (validate_slug, '--------', None), - (validate_slug, 'nohyphensoranything', None), - - (validate_slug, '', ValidationError), - (validate_slug, ' text ', ValidationError), - (validate_slug, ' ', ValidationError), - (validate_slug, 'some@mail.com', ValidationError), - (validate_slug, '你好', ValidationError), - (validate_slug, '\n', ValidationError), - - (validate_ipv4_address, '1.1.1.1', None), - (validate_ipv4_address, '255.0.0.0', None), - (validate_ipv4_address, '0.0.0.0', None), - - (validate_ipv4_address, '256.1.1.1', ValidationError), - (validate_ipv4_address, '25.1.1.', ValidationError), - (validate_ipv4_address, '25,1,1,1', ValidationError), - (validate_ipv4_address, '25.1 .1.1', ValidationError), - - (validate_comma_separated_integer_list, '1', None), - (validate_comma_separated_integer_list, '1,2,3', None), - (validate_comma_separated_integer_list, '1,2,3,', None), - - (validate_comma_separated_integer_list, '', ValidationError), - (validate_comma_separated_integer_list, 'a,b,c', ValidationError), - (validate_comma_separated_integer_list, '1, 2, 3', ValidationError), - - (MaxValueValidator(10), 10, None), - (MaxValueValidator(10), -10, None), - (MaxValueValidator(10), 0, None), - (MaxValueValidator(NOW), NOW, None), - (MaxValueValidator(NOW), NOW - timedelta(days=1), None), - - (MaxValueValidator(0), 1, ValidationError), - (MaxValueValidator(NOW), NOW + timedelta(days=1), ValidationError), - - (MinValueValidator(-10), -10, None), - (MinValueValidator(-10), 10, None), - (MinValueValidator(-10), 0, None), - (MinValueValidator(NOW), NOW, None), - (MinValueValidator(NOW), NOW + timedelta(days=1), None), - - (MinValueValidator(0), -1, ValidationError), - (MinValueValidator(NOW), NOW - timedelta(days=1), ValidationError), - - (MaxLengthValidator(10), '', None), - (MaxLengthValidator(10), 10*'x', None), - - (MaxLengthValidator(10), 15*'x', ValidationError), - - (MinLengthValidator(10), 15*'x', None), - (MinLengthValidator(10), 10*'x', None), - - (MinLengthValidator(10), '', ValidationError), - - (URLValidator(), 'http://www.djangoproject.com/', None), - (URLValidator(), 'http://localhost/', None), - (URLValidator(), 'http://example.com/', None), - (URLValidator(), 'http://www.example.com/', None), - (URLValidator(), 'http://www.example.com:8000/test', None), - (URLValidator(), 'http://valid-with-hyphens.com/', None), - (URLValidator(), 'http://subdomain.domain.com/', None), - (URLValidator(), 'http://200.8.9.10/', None), - (URLValidator(), 'http://200.8.9.10:8000/test', None), - (URLValidator(), 'http://valid-----hyphens.com/', None), - (URLValidator(), 'http://example.com?something=value', None), - (URLValidator(), 'http://example.com/index.php?something=value&another=value2', None), - - (URLValidator(), 'foo', ValidationError), - (URLValidator(), 'http://', ValidationError), - (URLValidator(), 'http://example', ValidationError), - (URLValidator(), 'http://example.', ValidationError), - (URLValidator(), 'http://.com', ValidationError), - (URLValidator(), 'http://invalid-.com', ValidationError), - (URLValidator(), 'http://-invalid.com', ValidationError), - (URLValidator(), 'http://inv-.alid-.com', ValidationError), - (URLValidator(), 'http://inv-.-alid.com', ValidationError), - - (BaseValidator(True), True, None), - (BaseValidator(True), False, ValidationError), - - (RegexValidator('.*'), '', None), - (RegexValidator(re.compile('.*')), '', None), - (RegexValidator('.*'), 'xxxxx', None), - - (RegexValidator('x'), 'y', ValidationError), - (RegexValidator(re.compile('x')), 'y', ValidationError), -) - -def create_simple_test_method(validator, expected, value, num): - if expected is not None and issubclass(expected, Exception): - test_mask = 'test_%s_raises_error_%d' - def test_func(self): - self.assertRaises(expected, validator, value) - else: - test_mask = 'test_%s_%d' - def test_func(self): - self.assertEqual(expected, validator(value)) - if isinstance(validator, types.FunctionType): - val_name = validator.__name__ - else: - val_name = validator.__class__.__name__ - test_name = test_mask % (val_name, num) - return test_name, test_func - -# Dynamically assemble a test class with the contents of TEST_DATA - -class TestSimpleValidators(TestCase): - def test_single_message(self): - v = ValidationError('Not Valid') - self.assertEquals(str(v), "[u'Not Valid']") - self.assertEquals(repr(v), "ValidationError([u'Not Valid'])") - - def test_message_list(self): - v = ValidationError(['First Problem', 'Second Problem']) - self.assertEquals(str(v), "[u'First Problem', u'Second Problem']") - self.assertEquals(repr(v), "ValidationError([u'First Problem', u'Second Problem'])") - - def test_message_dict(self): - v = ValidationError({'first': 'First Problem'}) - self.assertEquals(str(v), "{'first': 'First Problem'}") - self.assertEquals(repr(v), "ValidationError({'first': 'First Problem'})") - -test_counter = 0 -for validator, value, expected in TEST_DATA: - name, method = create_simple_test_method(validator, expected, value, test_counter) - setattr(TestSimpleValidators, name, method) - test_counter += 1 |