summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBrian Rosner <brosner@gmail.com>2008-06-30 15:38:16 +0000
committerBrian Rosner <brosner@gmail.com>2008-06-30 15:38:16 +0000
commit829fd5a9670a581309797f56bfc7e5140550e873 (patch)
tree6efe30b93fd5fc6564392f1dbaaf04c95a4b6bc2 /tests
parentc349ba4cfc2d137da393bddbda6e78fdb98c9c81 (diff)
newforms-admin: Merged from trunk up to [7808]. Fixed #7519, #7573
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7809 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
-rw-r--r--tests/regressiontests/extra_regress/__init__.py0
-rw-r--r--tests/regressiontests/extra_regress/models.py55
-rw-r--r--tests/regressiontests/fixtures_regress/fixtures/big-fixture.json83
-rw-r--r--tests/regressiontests/fixtures_regress/fixtures/model-inheritance.json4
-rw-r--r--tests/regressiontests/fixtures_regress/models.py48
-rw-r--r--tests/regressiontests/forms/error_messages.py2
-rw-r--r--tests/regressiontests/forms/fields.py14
-rw-r--r--tests/regressiontests/many_to_one_regress/models.py40
-rw-r--r--tests/regressiontests/model_fields/tests.py17
-rw-r--r--tests/regressiontests/model_inheritance_regress/models.py22
-rw-r--r--tests/regressiontests/model_inheritance_select_related/__init__.py0
-rw-r--r--tests/regressiontests/model_inheritance_select_related/models.py47
-rw-r--r--tests/regressiontests/queries/models.py132
-rw-r--r--tests/regressiontests/select_related_regress/__init__.py0
-rw-r--r--tests/regressiontests/select_related_regress/models.py60
-rw-r--r--tests/regressiontests/string_lookup/models.py6
-rw-r--r--tests/regressiontests/test_client_regress/models.py19
17 files changed, 481 insertions, 68 deletions
diff --git a/tests/regressiontests/extra_regress/__init__.py b/tests/regressiontests/extra_regress/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/extra_regress/__init__.py
diff --git a/tests/regressiontests/extra_regress/models.py b/tests/regressiontests/extra_regress/models.py
new file mode 100644
index 0000000000..3bcc3075ec
--- /dev/null
+++ b/tests/regressiontests/extra_regress/models.py
@@ -0,0 +1,55 @@
+import copy
+
+from django.db import models
+from django.db.models.query import Q
+
+
+class RevisionableModel(models.Model):
+ base = models.ForeignKey('self', null=True)
+ title = models.CharField(blank=True, max_length=255)
+
+ def __unicode__(self):
+ return u"%s (%s, %s)" % (self.title, self.id, self.base.id)
+
+ def save(self):
+ super(RevisionableModel, self).save()
+ if not self.base:
+ self.base = self
+ super(RevisionableModel, self).save()
+
+ def new_revision(self):
+ new_revision = copy.copy(self)
+ new_revision.pk = None
+ return new_revision
+
+__test__ = {"API_TESTS": """
+### Regression tests for #7314 and #7372
+
+>>> rm = RevisionableModel.objects.create(title='First Revision')
+>>> rm.pk, rm.base.pk
+(1, 1)
+
+>>> rm2 = rm.new_revision()
+>>> rm2.title = "Second Revision"
+>>> rm2.save()
+>>> print u"%s of %s" % (rm2.title, rm2.base.title)
+Second Revision of First Revision
+
+>>> rm2.pk, rm2.base.pk
+(2, 1)
+
+Queryset to match most recent revision:
+>>> qs = RevisionableModel.objects.extra(where=["%(table)s.id IN (SELECT MAX(rev.id) FROM %(table)s AS rev GROUP BY rev.base_id)" % {'table': RevisionableModel._meta.db_table,}],)
+>>> qs
+[<RevisionableModel: Second Revision (2, 1)>]
+
+Queryset to search for string in title:
+>>> qs2 = RevisionableModel.objects.filter(title__contains="Revision")
+>>> qs2
+[<RevisionableModel: First Revision (1, 1)>, <RevisionableModel: Second Revision (2, 1)>]
+
+Following queryset should return the most recent revision:
+>>> qs & qs2
+[<RevisionableModel: Second Revision (2, 1)>]
+
+"""}
diff --git a/tests/regressiontests/fixtures_regress/fixtures/big-fixture.json b/tests/regressiontests/fixtures_regress/fixtures/big-fixture.json
new file mode 100644
index 0000000000..e655fbbf3f
--- /dev/null
+++ b/tests/regressiontests/fixtures_regress/fixtures/big-fixture.json
@@ -0,0 +1,83 @@
+[
+ {
+ "pk": 6,
+ "model": "fixtures_regress.channel",
+ "fields": {
+ "name": "Business"
+ }
+ },
+
+ {
+ "pk": 1,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 1",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 2,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 2",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 3,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 3",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 4,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 4",
+ "channels": [6]
+ }
+ },
+
+ {
+ "pk": 5,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 5",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 6,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 6",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 7,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 7",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 8,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Article Title 8",
+ "channels": [6]
+ }
+ },
+ {
+ "pk": 9,
+ "model": "fixtures_regress.article",
+ "fields": {
+ "title": "Yet Another Article",
+ "channels": [6]
+ }
+ }
+] \ No newline at end of file
diff --git a/tests/regressiontests/fixtures_regress/fixtures/model-inheritance.json b/tests/regressiontests/fixtures_regress/fixtures/model-inheritance.json
new file mode 100644
index 0000000000..00c482b3dd
--- /dev/null
+++ b/tests/regressiontests/fixtures_regress/fixtures/model-inheritance.json
@@ -0,0 +1,4 @@
+[
+ {"pk": 1, "model": "fixtures_regress.parent", "fields": {"name": "fred"}},
+ {"pk": 1, "model": "fixtures_regress.child", "fields": {"data": "apple"}}
+]
diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py
index 59fc167d50..2c048dc0b8 100644
--- a/tests/regressiontests/fixtures_regress/models.py
+++ b/tests/regressiontests/fixtures_regress/models.py
@@ -20,7 +20,7 @@ class Plant(models.Model):
class Stuff(models.Model):
name = models.CharField(max_length=20, null=True)
owner = models.ForeignKey(User, null=True)
-
+
def __unicode__(self):
# Oracle doesn't distinguish between None and the empty string.
# This hack makes the test case pass using Oracle.
@@ -38,13 +38,29 @@ class Absolute(models.Model):
super(Absolute, self).__init__(*args, **kwargs)
Absolute.load_count += 1
+class Parent(models.Model):
+ name = models.CharField(max_length=10)
+
+class Child(Parent):
+ data = models.CharField(max_length=10)
+
+# Models to regresison check #7572
+class Channel(models.Model):
+ name = models.CharField(max_length=255)
+
+class Article(models.Model):
+ title = models.CharField(max_length=255)
+ channels = models.ManyToManyField(Channel)
+
+ class Meta:
+ ordering = ('id',)
__test__ = {'API_TESTS':"""
>>> from django.core import management
# Load a fixture that uses PK=1
>>> management.call_command('loaddata', 'sequence', verbosity=0)
-
+
# Create a new animal. Without a sequence reset, this new object
# will take a PK of 1 (on Postgres), and the save will fail.
# This is a regression test for ticket #3790.
@@ -61,9 +77,9 @@ __test__ = {'API_TESTS':"""
[<Stuff: None is owned by None>]
###############################################
-# Regression test for ticket #6436 --
+# Regression test for ticket #6436 --
# os.path.join will throw away the initial parts of a path if it encounters
-# an absolute path. This means that if a fixture is specified as an absolute path,
+# an absolute path. This means that if a fixture is specified as an absolute path,
# we need to make sure we don't discover the absolute path in every fixture directory.
>>> load_absolute_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'absolute.json')
@@ -94,4 +110,28 @@ No fixture data found for 'bad_fixture2'. (File format may be invalid.)
>>> sys.stderr = savestderr
+###############################################
+# Test for ticket #7565 -- PostgreSQL sequence resetting checks shouldn't
+# ascend to parent models when inheritance is used (since they are treated
+# individually).
+
+>>> management.call_command('loaddata', 'model-inheritance.json', verbosity=0)
+
+###############################################
+# Test for ticket #7572 -- MySQL has a problem if the same connection is
+# used to create tables, load data, and then query over that data.
+# To compensate, we close the connection after running loaddata.
+# This ensures that a new connection is opened when test queries are issued.
+
+>>> management.call_command('loaddata', 'big-fixture.json', verbosity=0)
+
+>>> articles = Article.objects.exclude(id=9)
+>>> articles.values_list('id', flat=True)
+[1, 2, 3, 4, 5, 6, 7, 8]
+
+# Just for good measure, run the same query again. Under the influence of
+# ticket #7572, this will give a different result to the previous call.
+>>> articles.values_list('id', flat=True)
+[1, 2, 3, 4, 5, 6, 7, 8]
+
"""}
diff --git a/tests/regressiontests/forms/error_messages.py b/tests/regressiontests/forms/error_messages.py
index 9f972f5b90..381282f121 100644
--- a/tests/regressiontests/forms/error_messages.py
+++ b/tests/regressiontests/forms/error_messages.py
@@ -237,7 +237,7 @@ ValidationError: [u'REQUIRED']
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
->>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com')
+>>> f.clean('http://www.broken.djangoproject.com')
Traceback (most recent call last):
...
ValidationError: [u'INVALID LINK']
diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py
index f3b6a96a1e..c9f3efdbda 100644
--- a/tests/regressiontests/forms/fields.py
+++ b/tests/regressiontests/forms/fields.py
@@ -887,7 +887,7 @@ u'http://www.google.com'
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
->>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain
+>>> f.clean('http://www.broken.djangoproject.com') # bad domain
Traceback (most recent call last):
...
ValidationError: [u'This URL appears to be a broken link.']
@@ -937,18 +937,24 @@ ValidationError: [u'This field is required.']
>>> f.clean(True)
True
>>> f.clean(False)
-False
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
>>> f.clean(1)
True
>>> f.clean(0)
-False
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
>>> f.clean('Django rocks')
True
>>> f.clean('True')
True
>>> f.clean('False')
-False
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
>>> f = BooleanField(required=False)
>>> f.clean('')
diff --git a/tests/regressiontests/many_to_one_regress/models.py b/tests/regressiontests/many_to_one_regress/models.py
index 4e49df1555..429bdd7558 100644
--- a/tests/regressiontests/many_to_one_regress/models.py
+++ b/tests/regressiontests/many_to_one_regress/models.py
@@ -28,6 +28,24 @@ class Child(models.Model):
parent = models.ForeignKey(Parent)
+# Multiple paths to the same model (#7110, #7125)
+class Category(models.Model):
+ name = models.CharField(max_length=20)
+
+ def __unicode__(self):
+ return self.name
+
+class Record(models.Model):
+ category = models.ForeignKey(Category)
+
+class Relation(models.Model):
+ left = models.ForeignKey(Record, related_name='left_set')
+ right = models.ForeignKey(Record, related_name='right_set')
+
+ def __unicode__(self):
+ return u"%s - %s" % (self.left.category.name, self.right.category.name)
+
+
__test__ = {'API_TESTS':"""
>>> Third.objects.create(id='3', name='An example')
<Third: Third object>
@@ -73,4 +91,26 @@ Traceback (most recent call last):
...
ValueError: Cannot assign "<First: First object>": "Child.parent" must be a "Parent" instance.
+# Test of multiple ForeignKeys to the same model (bug #7125)
+
+>>> c1 = Category.objects.create(name='First')
+>>> c2 = Category.objects.create(name='Second')
+>>> c3 = Category.objects.create(name='Third')
+>>> r1 = Record.objects.create(category=c1)
+>>> r2 = Record.objects.create(category=c1)
+>>> r3 = Record.objects.create(category=c2)
+>>> r4 = Record.objects.create(category=c2)
+>>> r5 = Record.objects.create(category=c3)
+>>> r = Relation.objects.create(left=r1, right=r2)
+>>> r = Relation.objects.create(left=r3, right=r4)
+>>> r = Relation.objects.create(left=r1, right=r3)
+>>> r = Relation.objects.create(left=r5, right=r2)
+>>> r = Relation.objects.create(left=r3, right=r2)
+
+>>> Relation.objects.filter(left__category__name__in=['First'], right__category__name__in=['Second'])
+[<Relation: First - Second>]
+
+>>> Category.objects.filter(record__left_set__right__category__name='Second').order_by('name')
+[<Category: First>, <Category: Second>]
+
"""}
diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
index e279a0669f..c2ba9ee008 100644
--- a/tests/regressiontests/model_fields/tests.py
+++ b/tests/regressiontests/model_fields/tests.py
@@ -15,4 +15,21 @@ Decimal("3.14")
Traceback (most recent call last):
...
ValidationError: [u'This value must be a decimal number.']
+
+>>> f = DecimalField(max_digits=5, decimal_places=1)
+>>> x = f.to_python(2)
+>>> y = f.to_python('2.6')
+
+>>> f.get_db_prep_save(x)
+u'2.0'
+>>> f.get_db_prep_save(y)
+u'2.6'
+>>> f.get_db_prep_save(None)
+>>> f.get_db_prep_lookup('exact', x)
+[u'2.0']
+>>> f.get_db_prep_lookup('exact', y)
+[u'2.6']
+>>> f.get_db_prep_lookup('exact', None)
+[None]
+
"""
diff --git a/tests/regressiontests/model_inheritance_regress/models.py b/tests/regressiontests/model_inheritance_regress/models.py
index 33e2e0e4f6..24d6186150 100644
--- a/tests/regressiontests/model_inheritance_regress/models.py
+++ b/tests/regressiontests/model_inheritance_regress/models.py
@@ -131,4 +131,26 @@ __test__ = {'API_TESTS':"""
>>> Child.objects.dates('created', 'month')
[datetime.datetime(2008, 6, 1, 0, 0)]
+# Regression test for #7276: calling delete() on a model with multi-table
+# inheritance should delete the associated rows from any ancestor tables, as
+# well as any descendent objects.
+
+>>> ident = ItalianRestaurant.objects.all()[0].id
+>>> Place.objects.get(pk=ident)
+<Place: Guido's All New House of Pasta the place>
+>>> xx = Restaurant.objects.create(name='a', address='xx', serves_hot_dogs=True, serves_pizza=False)
+
+# This should delete both Restuarants, plus the related places, plus the ItalianRestaurant.
+>>> Restaurant.objects.all().delete()
+
+>>> Place.objects.get(pk=ident)
+Traceback (most recent call last):
+...
+DoesNotExist: Place matching query does not exist.
+
+>>> ItalianRestaurant.objects.get(pk=ident)
+Traceback (most recent call last):
+...
+DoesNotExist: ItalianRestaurant matching query does not exist.
+
"""}
diff --git a/tests/regressiontests/model_inheritance_select_related/__init__.py b/tests/regressiontests/model_inheritance_select_related/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/model_inheritance_select_related/__init__.py
diff --git a/tests/regressiontests/model_inheritance_select_related/models.py b/tests/regressiontests/model_inheritance_select_related/models.py
new file mode 100644
index 0000000000..a97ecaadea
--- /dev/null
+++ b/tests/regressiontests/model_inheritance_select_related/models.py
@@ -0,0 +1,47 @@
+"""
+Regression tests for the interaction between model inheritance and
+select_related().
+"""
+
+from django.db import models
+
+class Place(models.Model):
+ name = models.CharField(max_length=50)
+
+ class Meta:
+ ordering = ('name',)
+
+ def __unicode__(self):
+ return u"%s the place" % self.name
+
+class Restaurant(Place):
+ serves_sushi = models.BooleanField()
+ serves_steak = models.BooleanField()
+
+ def __unicode__(self):
+ return u"%s the restaurant" % self.name
+
+class Person(models.Model):
+ name = models.CharField(max_length=50)
+ favorite_restaurant = models.ForeignKey(Restaurant)
+
+ def __unicode__(self):
+ return self.name
+
+__test__ = {'API_TESTS':"""
+Regression test for #7246
+
+>>> r1 = Restaurant.objects.create(name="Nobu", serves_sushi=True, serves_steak=False)
+>>> r2 = Restaurant.objects.create(name="Craft", serves_sushi=False, serves_steak=True)
+>>> p1 = Person.objects.create(name="John", favorite_restaurant=r1)
+>>> p2 = Person.objects.create(name="Jane", favorite_restaurant=r2)
+
+>>> Person.objects.order_by('name').select_related()
+[<Person: Jane>, <Person: John>]
+
+>>> jane = Person.objects.order_by('name').select_related('favorite_restaurant')[0]
+>>> jane.favorite_restaurant.name
+u'Craft'
+
+"""}
+
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index c02ad73998..566411e513 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -3,13 +3,15 @@ Various complex queries that have been problematic in the past.
"""
import datetime
+import pickle
from django.db import models
from django.db.models.query import Q
class Tag(models.Model):
name = models.CharField(max_length=10)
- parent = models.ForeignKey('self', blank=True, null=True)
+ parent = models.ForeignKey('self', blank=True, null=True,
+ related_name='children')
def __unicode__(self):
return self.name
@@ -24,6 +26,14 @@ class Note(models.Model):
def __unicode__(self):
return self.note
+class Annotation(models.Model):
+ name = models.CharField(max_length=10)
+ tag = models.ForeignKey(Tag)
+ notes = models.ManyToManyField(Note)
+
+ def __unicode__(self):
+ return self.name
+
class ExtraInfo(models.Model):
info = models.CharField(max_length=100)
note = models.ForeignKey(Note)
@@ -162,85 +172,67 @@ class Child(models.Model):
person = models.OneToOneField(Member, primary_key=True)
parent = models.ForeignKey(Member, related_name="children")
+# Custom primary keys interfered with ordering in the past.
+class CustomPk(models.Model):
+ name = models.CharField(max_length=10, primary_key=True)
+ extra = models.CharField(max_length=10)
+
+ class Meta:
+ ordering = ['name', 'extra']
+
+class Related(models.Model):
+ custom = models.ForeignKey(CustomPk)
+
__test__ = {'API_TESTS':"""
->>> t1 = Tag(name='t1')
->>> t1.save()
->>> t2 = Tag(name='t2', parent=t1)
->>> t2.save()
->>> t3 = Tag(name='t3', parent=t1)
->>> t3.save()
->>> t4 = Tag(name='t4', parent=t3)
->>> t4.save()
->>> t5 = Tag(name='t5', parent=t3)
->>> t5.save()
+>>> t1 = Tag.objects.create(name='t1')
+>>> t2 = Tag.objects.create(name='t2', parent=t1)
+>>> t3 = Tag.objects.create(name='t3', parent=t1)
+>>> t4 = Tag.objects.create(name='t4', parent=t3)
+>>> t5 = Tag.objects.create(name='t5', parent=t3)
->>> n1 = Note(note='n1', misc='foo')
->>> n1.save()
->>> n2 = Note(note='n2', misc='bar')
->>> n2.save()
->>> n3 = Note(note='n3', misc='foo')
->>> n3.save()
+>>> n1 = Note.objects.create(note='n1', misc='foo')
+>>> n2 = Note.objects.create(note='n2', misc='bar')
+>>> n3 = Note.objects.create(note='n3', misc='foo')
Create these out of order so that sorting by 'id' will be different to sorting
by 'info'. Helps detect some problems later.
->>> e2 = ExtraInfo(info='e2', note=n2)
->>> e2.save()
->>> e1 = ExtraInfo(info='e1', note=n1)
->>> e1.save()
+>>> e2 = ExtraInfo.objects.create(info='e2', note=n2)
+>>> e1 = ExtraInfo.objects.create(info='e1', note=n1)
->>> a1 = Author(name='a1', num=1001, extra=e1)
->>> a1.save()
->>> a2 = Author(name='a2', num=2002, extra=e1)
->>> a2.save()
->>> a3 = Author(name='a3', num=3003, extra=e2)
->>> a3.save()
->>> a4 = Author(name='a4', num=4004, extra=e2)
->>> a4.save()
+>>> a1 = Author.objects.create(name='a1', num=1001, extra=e1)
+>>> a2 = Author.objects.create(name='a2', num=2002, extra=e1)
+>>> a3 = Author.objects.create(name='a3', num=3003, extra=e2)
+>>> a4 = Author.objects.create(name='a4', num=4004, extra=e2)
>>> time1 = datetime.datetime(2007, 12, 19, 22, 25, 0)
>>> time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
>>> time3 = datetime.datetime(2007, 12, 20, 22, 25, 0)
>>> time4 = datetime.datetime(2007, 12, 20, 21, 0, 0)
->>> i1 = Item(name='one', created=time1, modified=time1, creator=a1, note=n3)
->>> i1.save()
+>>> i1 = Item.objects.create(name='one', created=time1, modified=time1, creator=a1, note=n3)
>>> i1.tags = [t1, t2]
->>> i2 = Item(name='two', created=time2, creator=a2, note=n2)
->>> i2.save()
+>>> i2 = Item.objects.create(name='two', created=time2, creator=a2, note=n2)
>>> i2.tags = [t1, t3]
->>> i3 = Item(name='three', created=time3, creator=a2, note=n3)
->>> i3.save()
->>> i4 = Item(name='four', created=time4, creator=a4, note=n3)
->>> i4.save()
+>>> i3 = Item.objects.create(name='three', created=time3, creator=a2, note=n3)
+>>> i4 = Item.objects.create(name='four', created=time4, creator=a4, note=n3)
>>> i4.tags = [t4]
->>> r1 = Report(name='r1', creator=a1)
->>> r1.save()
->>> r2 = Report(name='r2', creator=a3)
->>> r2.save()
->>> r3 = Report(name='r3')
->>> r3.save()
+>>> r1 = Report.objects.create(name='r1', creator=a1)
+>>> r2 = Report.objects.create(name='r2', creator=a3)
+>>> r3 = Report.objects.create(name='r3')
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
will be rank3, rank2, rank1.
->>> rank1 = Ranking(rank=2, author=a2)
->>> rank1.save()
->>> rank2 = Ranking(rank=1, author=a3)
->>> rank2.save()
->>> rank3 = Ranking(rank=3, author=a1)
->>> rank3.save()
+>>> rank1 = Ranking.objects.create(rank=2, author=a2)
+>>> rank2 = Ranking.objects.create(rank=1, author=a3)
+>>> rank3 = Ranking.objects.create(rank=3, author=a1)
->>> c1 = Cover(title="first", item=i4)
->>> c1.save()
->>> c2 = Cover(title="second", item=i2)
->>> c2.save()
+>>> c1 = Cover.objects.create(title="first", item=i4)
+>>> c2 = Cover.objects.create(title="second", item=i2)
->>> n1 = Number(num=4)
->>> n1.save()
->>> n2 = Number(num=8)
->>> n2.save()
->>> n3 = Number(num=12)
->>> n3.save()
+>>> num1 = Number.objects.create(num=4)
+>>> num2 = Number.objects.create(num=8)
+>>> num3 = Number.objects.create(num=12)
Bug #1050
>>> Item.objects.filter(tags__isnull=True)
@@ -346,6 +338,10 @@ Bug #1878, #2939
4
>>> xx.delete()
+Bug #7323
+>>> Item.objects.values('creator', 'name').count()
+4
+
Bug #2253
>>> q1 = Item.objects.order_by('name')
>>> q2 = Item.objects.filter(id=i1.id)
@@ -387,6 +383,10 @@ Bug #4510
>>> Author.objects.filter(report__name='r1')
[<Author: a1>]
+Bug #7378
+>>> a1.report_set.all()
+[<Report: r1>]
+
Bug #5324, #6704
>>> Item.objects.filter(tags__name='t4')
[<Item: four>]
@@ -791,5 +791,19 @@ Empty querysets can be merged with others.
>>> Note.objects.all() & Note.objects.none()
[]
+Bug #7204, #7506 -- make sure querysets with related fields can be pickled. If
+this doesn't crash, it's a Good Thing.
+>>> out = pickle.dumps(Item.objects.all())
+
+Bug #7277
+>>> ann1 = Annotation.objects.create(name='a1', tag=t1)
+>>> ann1.notes.add(n1)
+>>> n1.annotation_set.filter(Q(tag=t5) | Q(tag__children=t5) | Q(tag__children__children=t5))
+[<Annotation: a1>]
+
+Bug #7371
+>>> Related.objects.order_by('custom')
+[]
+
"""}
diff --git a/tests/regressiontests/select_related_regress/__init__.py b/tests/regressiontests/select_related_regress/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/select_related_regress/__init__.py
diff --git a/tests/regressiontests/select_related_regress/models.py b/tests/regressiontests/select_related_regress/models.py
new file mode 100644
index 0000000000..1688053e2d
--- /dev/null
+++ b/tests/regressiontests/select_related_regress/models.py
@@ -0,0 +1,60 @@
+from django.db import models
+
+class Building(models.Model):
+ name = models.CharField(max_length=10)
+
+ def __unicode__(self):
+ return u"Building: %s" % self.name
+
+class Device(models.Model):
+ building = models.ForeignKey('Building')
+ name = models.CharField(max_length=10)
+
+ def __unicode__(self):
+ return u"device '%s' in building %s" % (self.name, self.building)
+
+class Port(models.Model):
+ device = models.ForeignKey('Device')
+ number = models.CharField(max_length=10)
+
+ def __unicode__(self):
+ return u"%s/%s" % (self.device.name, self.number)
+
+class Connection(models.Model):
+ start = models.ForeignKey(Port, related_name='connection_start',
+ unique=True)
+ end = models.ForeignKey(Port, related_name='connection_end', unique=True)
+
+ def __unicode__(self):
+ return u"%s to %s" % (self.start, self.end)
+
+__test__ = {'API_TESTS': """
+Regression test for bug #7110. When using select_related(), we must query the
+Device and Building tables using two different aliases (each) in order to
+differentiate the start and end Connection fields. The net result is that both
+the "connections = ..." queries here should give the same results.
+
+>>> b=Building.objects.create(name='101')
+>>> dev1=Device.objects.create(name="router", building=b)
+>>> dev2=Device.objects.create(name="switch", building=b)
+>>> dev3=Device.objects.create(name="server", building=b)
+>>> port1=Port.objects.create(number='4',device=dev1)
+>>> port2=Port.objects.create(number='7',device=dev2)
+>>> port3=Port.objects.create(number='1',device=dev3)
+>>> c1=Connection.objects.create(start=port1, end=port2)
+>>> c2=Connection.objects.create(start=port2, end=port3)
+
+>>> connections=Connection.objects.filter(start__device__building=b, end__device__building=b).order_by('id')
+>>> [(c.id, unicode(c.start), unicode(c.end)) for c in connections]
+[(1, u'router/4', u'switch/7'), (2, u'switch/7', u'server/1')]
+
+>>> connections=Connection.objects.filter(start__device__building=b, end__device__building=b).select_related().order_by('id')
+>>> [(c.id, unicode(c.start), unicode(c.end)) for c in connections]
+[(1, u'router/4', u'switch/7'), (2, u'switch/7', u'server/1')]
+
+# This final query should only join seven tables (port, device and building
+# twice each, plus connection once).
+>>> connections.query.count_active_tables()
+7
+
+"""}
diff --git a/tests/regressiontests/string_lookup/models.py b/tests/regressiontests/string_lookup/models.py
index 1bdb2d4452..39e7955592 100644
--- a/tests/regressiontests/string_lookup/models.py
+++ b/tests/regressiontests/string_lookup/models.py
@@ -97,6 +97,12 @@ __test__ = {'API_TESTS': ur"""
>>> Article.objects.get(text__exact='The quick brown fox jumps over the lazy dog.')
<Article: Article Test>
+# Regression tests for #2170: test case sensitiveness
+>>> Article.objects.filter(text__exact='tHe qUick bRown fOx jUmps over tHe lazy dog.')
+[]
+>>> Article.objects.filter(text__iexact='tHe qUick bRown fOx jUmps over tHe lazy dog.')
+[<Article: Article Test>]
+
>>> Article.objects.get(text__contains='quick brown fox')
<Article: Article Test>
diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
index a204ec3e72..37e81668b6 100644
--- a/tests/regressiontests/test_client_regress/models.py
+++ b/tests/regressiontests/test_client_regress/models.py
@@ -318,3 +318,22 @@ class ExceptionTests(TestCase):
self.client.get("/test_client_regress/staff_only/")
except SuspiciousOperation:
self.fail("Staff should be able to visit this page")
+
+# We need two different tests to check URLconf subsitution - one to check
+# it was changed, and another one (without self.urls) to check it was reverted on
+# teardown. This pair of tests relies upon the alphabetical ordering of test execution.
+class UrlconfSubstitutionTests(TestCase):
+ urls = 'regressiontests.test_client_regress.urls'
+
+ def test_urlconf_was_changed(self):
+ "TestCase can enforce a custom URLConf on a per-test basis"
+ url = reverse('arg_view', args=['somename'])
+ self.assertEquals(url, '/arg_view/somename/')
+
+# This test needs to run *after* UrlconfSubstitutionTests; the zz prefix in the
+# name is to ensure alphabetical ordering.
+class zzUrlconfSubstitutionTests(TestCase):
+ def test_urlconf_was_reverted(self):
+ "URLconf is reverted to original value after modification in a TestCase"
+ url = reverse('arg_view', args=['somename'])
+ self.assertEquals(url, '/test_client_regress/arg_view/somename/')