summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2005-08-25 22:51:30 +0000
committerAdrian Holovaty <adrian@holovaty.com>2005-08-25 22:51:30 +0000
commit25264c86048d442a4885dfebae94510e2fa0c1e4 (patch)
treebb02799b624fb0d6f931d208509ffbb50d00e358 /tests
parentaec0a73d73324820c767758afd250fc21a2896ef (diff)
Fixed #122 -- BIG, BACKWARDS-INCOMPATIBLE CHANGE. Changed model syntax to use fieldname=FieldClass() syntax. See ModelSyntaxChangeInstructions for important information on how to change your models
git-svn-id: http://code.djangoproject.com/svn/django/trunk@549 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
-rw-r--r--tests/testapp/models/__init__.py3
-rw-r--r--tests/testapp/models/basic.py6
-rw-r--r--tests/testapp/models/custom_methods.py6
-rw-r--r--tests/testapp/models/custom_pk.py11
-rw-r--r--tests/testapp/models/get_latest.py9
-rw-r--r--tests/testapp/models/lookup.py9
-rw-r--r--tests/testapp/models/m2m_intermediary.py30
-rw-r--r--tests/testapp/models/m2o_recursive.py18
-rw-r--r--tests/testapp/models/m2o_recursive2.py22
-rw-r--r--tests/testapp/models/many_to_many.py10
-rw-r--r--tests/testapp/models/many_to_one.py54
-rw-r--r--tests/testapp/models/many_to_one_null.py77
-rw-r--r--tests/testapp/models/one_to_one.py27
-rw-r--r--tests/testapp/models/ordering.py17
-rw-r--r--tests/testapp/models/repr.py8
-rw-r--r--tests/testapp/models/save_delete_hooks.py6
-rw-r--r--tests/testapp/models/subclassing.py168
17 files changed, 359 insertions, 122 deletions
diff --git a/tests/testapp/models/__init__.py b/tests/testapp/models/__init__.py
index d76059ec74..0fab083922 100644
--- a/tests/testapp/models/__init__.py
+++ b/tests/testapp/models/__init__.py
@@ -1,3 +1,4 @@
__all__ = ['basic', 'repr', 'custom_methods', 'many_to_one', 'many_to_many',
'ordering', 'lookup', 'get_latest', 'm2m_intermediary', 'one_to_one',
- 'm2o_recursive', 'm2o_recursive2', 'save_delete_hooks', 'custom_pk']
+ 'm2o_recursive', 'm2o_recursive2', 'save_delete_hooks', 'custom_pk',
+ 'subclassing', 'many_to_one_null']
diff --git a/tests/testapp/models/basic.py b/tests/testapp/models/basic.py
index c51ceccb9d..ebd784137a 100644
--- a/tests/testapp/models/basic.py
+++ b/tests/testapp/models/basic.py
@@ -7,10 +7,8 @@ This is a basic model with only two non-primary-key fields.
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100, default='Default headline'),
- meta.DateTimeField('pub_date'),
- )
+ headline = meta.CharField(maxlength=100, default='Default headline')
+ pub_date = meta.DateTimeField()
API_TESTS = """
# No articles are in the system yet.
diff --git a/tests/testapp/models/custom_methods.py b/tests/testapp/models/custom_methods.py
index f674b9c286..4f175752b4 100644
--- a/tests/testapp/models/custom_methods.py
+++ b/tests/testapp/models/custom_methods.py
@@ -23,10 +23,8 @@ namespace as custom methods.
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateField('pub_date'),
- )
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateField()
def __repr__(self):
return self.headline
diff --git a/tests/testapp/models/custom_pk.py b/tests/testapp/models/custom_pk.py
index d7407404f8..b7ebd61d4b 100644
--- a/tests/testapp/models/custom_pk.py
+++ b/tests/testapp/models/custom_pk.py
@@ -11,12 +11,11 @@ fails.
from django.core import meta
class Employee(meta.Model):
- fields = (
- meta.CharField('employee_code', maxlength=10, primary_key=True),
- meta.CharField('first_name', maxlength=20),
- meta.CharField('last_name', maxlength=20),
- )
- ordering = ('last_name', 'first_name')
+ employee_code = meta.CharField(maxlength=10, primary_key=True)
+ first_name = meta.CharField(maxlength=20)
+ last_name = meta.CharField(maxlength=20)
+ class META:
+ ordering = ('last_name', 'first_name')
def __repr__(self):
return "%s %s" % (self.first_name, self.last_name)
diff --git a/tests/testapp/models/get_latest.py b/tests/testapp/models/get_latest.py
index 2bd5a6660b..86697e85a7 100644
--- a/tests/testapp/models/get_latest.py
+++ b/tests/testapp/models/get_latest.py
@@ -11,11 +11,10 @@ date farthest into the future."
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateTimeField('pub_date'),
- )
- get_latest_by = 'pub_date'
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateTimeField()
+ class META:
+ get_latest_by = 'pub_date'
def __repr__(self):
return self.headline
diff --git a/tests/testapp/models/lookup.py b/tests/testapp/models/lookup.py
index 4567b1f106..bb8f4aaad1 100644
--- a/tests/testapp/models/lookup.py
+++ b/tests/testapp/models/lookup.py
@@ -7,11 +7,10 @@ This demonstrates features of the database API.
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateTimeField('pub_date'),
- )
- ordering = ('-pub_date', 'headline')
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateTimeField()
+ class META:
+ ordering = ('-pub_date', 'headline')
def __repr__(self):
return self.headline
diff --git a/tests/testapp/models/m2m_intermediary.py b/tests/testapp/models/m2m_intermediary.py
index 30d0bb2ac2..2a20072e03 100644
--- a/tests/testapp/models/m2m_intermediary.py
+++ b/tests/testapp/models/m2m_intermediary.py
@@ -13,49 +13,43 @@ writer").
from django.core import meta
class Reporter(meta.Model):
- fields = (
- meta.CharField('first_name', maxlength=30),
- meta.CharField('last_name', maxlength=30),
- )
+ first_name = meta.CharField(maxlength=30)
+ last_name = meta.CharField(maxlength=30)
def __repr__(self):
return "%s %s" % (self.first_name, self.last_name)
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateField('pub_date'),
- )
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateField()
def __repr__(self):
return self.headline
class Writer(meta.Model):
- fields = (
- meta.ForeignKey(Reporter),
- meta.ForeignKey(Article),
- meta.CharField('position', maxlength=100),
- )
+ reporter = meta.ForeignKey(Reporter)
+ article = meta.ForeignKey(Article)
+ position = meta.CharField(maxlength=100)
def __repr__(self):
return '%r (%s)' % (self.get_reporter(), self.position)
API_TESTS = """
# Create a few Reporters.
->>> r1 = reporters.Reporter(id=None, first_name='John', last_name='Smith')
+>>> r1 = reporters.Reporter(first_name='John', last_name='Smith')
>>> r1.save()
->>> r2 = reporters.Reporter(id=None, first_name='Jane', last_name='Doe')
+>>> r2 = reporters.Reporter(first_name='Jane', last_name='Doe')
>>> r2.save()
# Create an Article.
>>> from datetime import datetime
->>> a = articles.Article(id=None, headline='This is a test', pub_date=datetime(2005, 7, 27))
+>>> a = articles.Article(headline='This is a test', pub_date=datetime(2005, 7, 27))
>>> a.save()
# Create a few Writers.
->>> w1 = writers.Writer(id=None, reporter_id=r1.id, article_id=a.id, position='Main writer')
+>>> w1 = writers.Writer(reporter=r1, article=a, position='Main writer')
>>> w1.save()
->>> w2 = writers.Writer(id=None, reporter_id=r2.id, article_id=a.id, position='Contributor')
+>>> w2 = writers.Writer(reporter=r2, article=a, position='Contributor')
>>> w2.save()
# Play around with the API.
diff --git a/tests/testapp/models/m2o_recursive.py b/tests/testapp/models/m2o_recursive.py
index a0d211fc2c..27d13b4e7e 100644
--- a/tests/testapp/models/m2o_recursive.py
+++ b/tests/testapp/models/m2o_recursive.py
@@ -7,29 +7,25 @@ To define a many-to-one relationship between a model and itself, use
In this example, a ``Category`` is related to itself. That is, each
``Category`` has a parent ``Category``.
-Because of this recursive relationship, we need to tell Django what the
-relationships should be called. Set ``rel_name`` for this, and set
-``related_name`` to designate what the reverse relationship is called.
+Set ``related_name`` to designate what the reverse relationship is called.
"""
from django.core import meta
class Category(meta.Model):
- module_name = 'categories'
- fields = (
- meta.CharField('name', maxlength=20),
- meta.ForeignKey('self', null=True,
- rel_name='parent', related_name='child'),
- )
+ name = meta.CharField(maxlength=20)
+ parent = meta.ForeignKey('self', null=True, related_name='child')
+ class META:
+ module_name = 'categories'
def __repr__(self):
return self.name
API_TESTS = """
# Create a few Category objects.
->>> r = categories.Category(id=None, name='Root category', parent_id=None)
+>>> r = categories.Category(id=None, name='Root category', parent=None)
>>> r.save()
->>> c = categories.Category(id=None, name='Child category', parent_id=r.id)
+>>> c = categories.Category(id=None, name='Child category', parent=r)
>>> c.save()
>>> r.get_child_list()
diff --git a/tests/testapp/models/m2o_recursive2.py b/tests/testapp/models/m2o_recursive2.py
index ae1407ad31..52aa0f8b69 100644
--- a/tests/testapp/models/m2o_recursive2.py
+++ b/tests/testapp/models/m2o_recursive2.py
@@ -4,36 +4,28 @@
In this example, a ``Person`` can have a ``mother`` and ``father`` -- both of
which are other ``Person`` objects.
-Because a ``Person`` has multiple relationships to ``Person``, we need to
-distinguish the relationships. Set ``rel_name`` to tell Django what the
-relationship should be called, because ``Person`` has two relationships to the
-same model. Also, set ``related_name`` to designate what the reverse
-relationship is called.
+Set ``related_name`` to designate what the reverse relationship is called.
"""
from django.core import meta
class Person(meta.Model):
- fields = (
- meta.CharField('full_name', maxlength=20),
- meta.ForeignKey('self', null=True, rel_name='mother',
- related_name='mothers_child'),
- meta.ForeignKey('self', null=True, rel_name='father',
- related_name='fathers_child'),
- )
+ full_name = meta.CharField(maxlength=20)
+ mother = meta.ForeignKey('self', null=True, related_name='mothers_child')
+ father = meta.ForeignKey('self', null=True, related_name='fathers_child')
def __repr__(self):
return self.full_name
API_TESTS = """
# Create two Person objects -- the mom and dad in our family.
->>> dad = persons.Person(id=None, full_name='John Smith Senior', mother_id=None, father_id=None)
+>>> dad = persons.Person(full_name='John Smith Senior', mother=None, father=None)
>>> dad.save()
->>> mom = persons.Person(id=None, full_name='Jane Smith', mother_id=None, father_id=None)
+>>> mom = persons.Person(full_name='Jane Smith', mother=None, father=None)
>>> mom.save()
# Give mom and dad a kid.
->>> kid = persons.Person(id=None, full_name='John Smith Junior', mother_id=mom.id, father_id=dad.id)
+>>> kid = persons.Person(full_name='John Smith Junior', mother=mom, father=dad)
>>> kid.save()
>>> kid.get_mother()
diff --git a/tests/testapp/models/many_to_many.py b/tests/testapp/models/many_to_many.py
index 283a004ca4..91addafe9b 100644
--- a/tests/testapp/models/many_to_many.py
+++ b/tests/testapp/models/many_to_many.py
@@ -10,18 +10,14 @@ and a publication has multiple articles.
from django.core import meta
class Publication(meta.Model):
- fields = (
- meta.CharField('title', maxlength=30),
- )
+ title = meta.CharField(maxlength=30)
def __repr__(self):
return self.title
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.ManyToManyField(Publication),
- )
+ headline = meta.CharField(maxlength=100)
+ publications = meta.ManyToManyField(Publication)
def __repr__(self):
return self.headline
diff --git a/tests/testapp/models/many_to_one.py b/tests/testapp/models/many_to_one.py
index a5bb16cb06..91dae95614 100644
--- a/tests/testapp/models/many_to_one.py
+++ b/tests/testapp/models/many_to_one.py
@@ -1,42 +1,38 @@
"""
4. Many-to-one relationships
-To define a many-to-one relationship, use ForeignKey().
+To define a many-to-one relationship, use ``ForeignKey()`` .
"""
from django.core import meta
class Reporter(meta.Model):
- fields = (
- meta.CharField('first_name', maxlength=30),
- meta.CharField('last_name', maxlength=30),
- )
+ first_name = meta.CharField(maxlength=30)
+ last_name = meta.CharField(maxlength=30)
def __repr__(self):
return "%s %s" % (self.first_name, self.last_name)
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateField('pub_date'),
- meta.ForeignKey(Reporter),
- )
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateField()
+ reporter = meta.ForeignKey(Reporter)
def __repr__(self):
return self.headline
API_TESTS = """
# Create a Reporter.
->>> r = reporters.Reporter(id=None, first_name='John', last_name='Smith')
+>>> r = reporters.Reporter(first_name='John', last_name='Smith')
>>> r.save()
# Create an Article.
>>> from datetime import datetime
->>> a = articles.Article(id=None, headline='This is a test', pub_date=datetime(2005, 7, 27), reporter_id=r.id)
+>>> a = articles.Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter=r)
>>> a.save()
>>> a.reporter_id
-1L
+1
>>> a.get_reporter()
John Smith
@@ -47,7 +43,7 @@ John Smith
('John', 'Smith')
# Create an Article via the Reporter object.
->>> new_article = r.add_article(headline="John's second story", pub_date=datetime(2005, 7, 28))
+>>> new_article = r.add_article(headline="John's second story", pub_date=datetime(2005, 7, 29))
>>> new_article
John's second story
>>> new_article.reporter_id
@@ -61,7 +57,7 @@ John's second story
This is a test
>>> r.get_article_count()
-2L
+2
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
@@ -70,4 +66,32 @@ This is a test
>>> articles.get_list(reporter__first_name__exact='John', order_by=['pub_date'])
[This is a test, John's second story]
+# Find all Articles for the Reporter whose ID is 1.
+>>> articles.get_list(reporter__id__exact=1, order_by=['pub_date'])
+[This is a test, John's second story]
+
+# Note you need two underscores between "reporter" and "id" -- not one.
+>>> articles.get_list(reporter_id__exact=1)
+Traceback (most recent call last):
+ ...
+TypeError: got unexpected keyword argument 'reporter_id__exact'
+
+# "pk" shortcut syntax works in a related context, too.
+>>> articles.get_list(reporter__pk=1, order_by=['pub_date'])
+[This is a test, John's second story]
+
+# You can also instantiate an Article by passing
+# the Reporter's ID instead of a Reporter object.
+>>> a3 = articles.Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id=r.id)
+>>> a3.save()
+>>> a3.reporter_id
+1
+>>> a3.get_reporter()
+John Smith
+
+# Similarly, the reporter ID can be a string.
+>>> a4 = articles.Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1")
+>>> a4.save()
+>>> a4.get_reporter()
+John Smith
"""
diff --git a/tests/testapp/models/many_to_one_null.py b/tests/testapp/models/many_to_one_null.py
new file mode 100644
index 0000000000..dcf6373e68
--- /dev/null
+++ b/tests/testapp/models/many_to_one_null.py
@@ -0,0 +1,77 @@
+"""
+16. Many-to-one relationships that can be null
+
+To define a many-to-one relationship, use ``ForeignKey()`` with ``null=True`` .
+"""
+
+from django.core import meta
+
+class Reporter(meta.Model):
+ name = meta.CharField(maxlength=30)
+
+ def __repr__(self):
+ return self.name
+
+class Article(meta.Model):
+ headline = meta.CharField(maxlength=100)
+ reporter = meta.ForeignKey(Reporter, null=True)
+
+ def __repr__(self):
+ return self.headline
+
+API_TESTS = """
+# Create a Reporter.
+>>> r = reporters.Reporter(name='John Smith')
+>>> r.save()
+
+# Create an Article.
+>>> a = articles.Article(headline="First", reporter=r)
+>>> a.save()
+
+>>> a.reporter_id
+1
+
+>>> a.get_reporter()
+John Smith
+
+# Article objects have access to their related Reporter objects.
+>>> r = a.get_reporter()
+
+# Create an Article via the Reporter object.
+>>> a2 = r.add_article(headline="Second")
+>>> a2
+Second
+>>> a2.reporter_id
+1
+
+# Reporter objects have access to their related Article objects.
+>>> r.get_article_list(order_by=['headline'])
+[First, Second]
+>>> r.get_article(headline__startswith='Fir')
+First
+>>> r.get_article_count()
+2
+
+# Create an Article with no Reporter by passing "reporter=None".
+>>> a3 = articles.Article(headline="Third", reporter=None)
+>>> a3.save()
+>>> a3.id
+3
+>>> a3.reporter_id
+>>> print a3.reporter_id
+None
+>>> a3 = articles.get_object(pk=3)
+>>> print a3.reporter_id
+None
+
+# An article's get_reporter() method throws ReporterDoesNotExist
+# if the reporter is set to None.
+>>> a3.get_reporter()
+Traceback (most recent call last):
+ ...
+ReporterDoesNotExist
+
+# To retrieve the articles with no reporters set, use "reporter__isnull=True".
+>>> articles.get_list(reporter__isnull=True)
+[Third]
+"""
diff --git a/tests/testapp/models/one_to_one.py b/tests/testapp/models/one_to_one.py
index d150daea8e..51b3efe733 100644
--- a/tests/testapp/models/one_to_one.py
+++ b/tests/testapp/models/one_to_one.py
@@ -9,33 +9,29 @@ In this example, a ``Place`` optionally can be a ``Restaurant``.
from django.core import meta
class Place(meta.Model):
- fields = (
- meta.CharField('name', maxlength=50),
- meta.CharField('address', maxlength=80),
- )
+ name = meta.CharField(maxlength=50)
+ address = meta.CharField(maxlength=80)
def __repr__(self):
return "%s the place" % self.name
class Restaurant(meta.Model):
- fields = (
- meta.OneToOneField(Place),
- meta.BooleanField('serves_hot_dogs'),
- meta.BooleanField('serves_pizza'),
- )
+ place = meta.OneToOneField(Place)
+ serves_hot_dogs = meta.BooleanField()
+ serves_pizza = meta.BooleanField()
def __repr__(self):
return "%s the restaurant" % self.get_place().name
API_TESTS = """
# Create a couple of Places.
->>> p1 = places.Place(id=None, name='Demon Dogs', address='944 W. Fullerton')
+>>> p1 = places.Place(name='Demon Dogs', address='944 W. Fullerton')
>>> p1.save()
->>> p2 = places.Place(id=None, name='Ace Hardware', address='1013 N. Ashland')
+>>> p2 = places.Place(name='Ace Hardware', address='1013 N. Ashland')
>>> p2.save()
# Create a Restaurant. Pass the ID of the "parent" object as this object's ID.
->>> r = restaurants.Restaurant(id=p1.id, serves_hot_dogs=True, serves_pizza=False)
+>>> r = restaurants.Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
>>> r.save()
# A Restaurant can access its place.
@@ -50,7 +46,7 @@ Demon Dogs the restaurant
>>> p2.get_restaurant()
Traceback (most recent call last):
...
-RestaurantDoesNotExist: Restaurant does not exist for {'id__exact': ...}
+RestaurantDoesNotExist: Restaurant does not exist for {'place__id__exact': ...}
# restaurants.get_list() just returns the Restaurants, not the Places.
>>> restaurants.get_list()
@@ -60,4 +56,9 @@ RestaurantDoesNotExist: Restaurant does not exist for {'id__exact': ...}
# Restaurants.
>>> places.get_list(order_by=['name'])
[Ace Hardware the place, Demon Dogs the place]
+
+>>> restaurants.get_object(place__id__exact=1)
+Demon Dogs the restaurant
+>>> restaurants.get_object(pk=1)
+Demon Dogs the restaurant
"""
diff --git a/tests/testapp/models/ordering.py b/tests/testapp/models/ordering.py
index 0efa0638df..b7b68b3158 100644
--- a/tests/testapp/models/ordering.py
+++ b/tests/testapp/models/ordering.py
@@ -16,11 +16,10 @@ undefined -- not random, just undefined.
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateTimeField('pub_date'),
- )
- ordering = ('-pub_date', 'headline')
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateTimeField()
+ class META:
+ ordering = ('-pub_date', 'headline')
def __repr__(self):
return self.headline
@@ -28,13 +27,13 @@ class Article(meta.Model):
API_TESTS = """
# Create a couple of Articles.
>>> from datetime import datetime
->>> a1 = articles.Article(id=None, headline='Article 1', pub_date=datetime(2005, 7, 26))
+>>> a1 = articles.Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
>>> a1.save()
->>> a2 = articles.Article(id=None, headline='Article 2', pub_date=datetime(2005, 7, 27))
+>>> a2 = articles.Article(headline='Article 2', pub_date=datetime(2005, 7, 27))
>>> a2.save()
->>> a3 = articles.Article(id=None, headline='Article 3', pub_date=datetime(2005, 7, 27))
+>>> a3 = articles.Article(headline='Article 3', pub_date=datetime(2005, 7, 27))
>>> a3.save()
->>> a4 = articles.Article(id=None, headline='Article 4', pub_date=datetime(2005, 7, 28))
+>>> a4 = articles.Article(headline='Article 4', pub_date=datetime(2005, 7, 28))
>>> a4.save()
# By default, articles.get_list() orders by pub_date descending, then
diff --git a/tests/testapp/models/repr.py b/tests/testapp/models/repr.py
index 00f78f967f..3d4daf22c9 100644
--- a/tests/testapp/models/repr.py
+++ b/tests/testapp/models/repr.py
@@ -11,10 +11,8 @@ automatically-generated admin.
from django.core import meta
class Article(meta.Model):
- fields = (
- meta.CharField('headline', maxlength=100),
- meta.DateTimeField('pub_date'),
- )
+ headline = meta.CharField(maxlength=100)
+ pub_date = meta.DateTimeField()
def __repr__(self):
return self.headline
@@ -22,7 +20,7 @@ class Article(meta.Model):
API_TESTS = """
# Create an Article.
>>> from datetime import datetime
->>> a = articles.Article(id=None, headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
+>>> a = articles.Article(headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
>>> a.save()
>>> repr(a)
diff --git a/tests/testapp/models/save_delete_hooks.py b/tests/testapp/models/save_delete_hooks.py
index 3c895b8bee..f0fa836f71 100644
--- a/tests/testapp/models/save_delete_hooks.py
+++ b/tests/testapp/models/save_delete_hooks.py
@@ -13,10 +13,8 @@ Django provides hooks for executing arbitrary code around ``save()`` and
from django.core import meta
class Person(meta.Model):
- fields = (
- meta.CharField('first_name', maxlength=20),
- meta.CharField('last_name', maxlength=20),
- )
+ first_name = meta.CharField(maxlength=20)
+ last_name = meta.CharField(maxlength=20)
def __repr__(self):
return "%s %s" % (self.first_name, self.last_name)
diff --git a/tests/testapp/models/subclassing.py b/tests/testapp/models/subclassing.py
new file mode 100644
index 0000000000..7ec8d37ff9
--- /dev/null
+++ b/tests/testapp/models/subclassing.py
@@ -0,0 +1,168 @@
+"""
+15. Subclassing models
+
+You can subclass another model to create a copy of it that behaves slightly
+differently.
+"""
+
+from django.core import meta
+
+# From the "Bare-bones model" example
+from django.models.basic import Article
+
+# From the "Adding __repr__()" example
+from django.models.repr import Article as ArticleWithRepr
+
+# From the "Specifying ordering" example
+from django.models.ordering import Article as ArticleWithOrdering
+
+# This uses all fields and metadata from Article and
+# adds a "section" field.
+class ArticleWithSection(Article):
+ section = meta.CharField(maxlength=30)
+ class META:
+ module_name = 'subarticles1'
+
+# This uses all fields and metadata from Article but
+# removes the "pub_date" field.
+class ArticleWithoutPubDate(Article):
+ class META:
+ module_name = 'subarticles2'
+ remove_fields = ('pub_date',)
+
+# This uses all fields and metadata from Article but
+# overrides the "pub_date" field.
+class ArticleWithFieldOverride(Article):
+ pub_date = meta.DateField() # overrides the old field, a DateTimeField
+ class META:
+ module_name = 'subarticles3'
+ # No need to add remove_fields = ('pub_date',)
+
+# This uses all fields and metadata from ArticleWithRepr and
+# makes a few additions/changes.
+class ArticleWithManyChanges(ArticleWithRepr):
+ section = meta.CharField(maxlength=30)
+ is_popular = meta.BooleanField()
+ pub_date = meta.DateField() # overrides the old field, a DateTimeField
+ class META:
+ module_name = 'subarticles4'
+
+# This uses all fields from ArticleWithOrdering but
+# changes the ordering parameter.
+class ArticleWithChangedMeta(ArticleWithOrdering):
+ class META:
+ module_name = 'subarticles5'
+ ordering = ('headline', 'pub_date')
+
+API_TESTS = """
+# No data is in the system yet.
+>>> subarticles1.get_list()
+[]
+>>> subarticles2.get_list()
+[]
+>>> subarticles3.get_list()
+[]
+
+# Create an ArticleWithSection.
+>>> from datetime import date, datetime
+>>> a1 = subarticles1.ArticleWithSection(headline='First', pub_date=datetime(2005, 8, 22), section='News')
+>>> a1.save()
+>>> a1
+<ArticleWithSection object>
+>>> a1.id
+1
+>>> a1.headline
+'First'
+>>> a1.pub_date
+datetime.datetime(2005, 8, 22, 0, 0)
+
+# Retrieve it again, to prove the fields have been saved.
+>>> a1 = subarticles1.get_object(pk=1)
+>>> a1.headline
+'First'
+>>> a1.pub_date
+datetime.datetime(2005, 8, 22, 0, 0)
+>>> a1.section
+'News'
+
+# Create an ArticleWithoutPubDate.
+>>> a2 = subarticles2.ArticleWithoutPubDate(headline='Second')
+>>> a2.save()
+>>> a2
+<ArticleWithoutPubDate object>
+>>> a2.id
+1
+>>> a2.pub_date
+Traceback (most recent call last):
+ ...
+AttributeError: 'ArticleWithoutPubDate' object has no attribute 'pub_date'
+
+# Retrieve it again, to prove the fields have been saved.
+>>> a2 = subarticles2.get_object(pk=1)
+>>> a2.headline
+'Second'
+>>> a2.pub_date
+Traceback (most recent call last):
+ ...
+AttributeError: 'ArticleWithoutPubDate' object has no attribute 'pub_date'
+
+# Create an ArticleWithFieldOverride.
+>>> a3 = subarticles3.ArticleWithFieldOverride(headline='Third', pub_date=date(2005, 8, 22))
+>>> a3.save()
+>>> a3
+<ArticleWithFieldOverride object>
+>>> a3.id
+1
+>>> a3.pub_date
+datetime.date(2005, 8, 22)
+
+# Retrieve it again, to prove the fields have been saved.
+>>> a3 = subarticles3.get_object(pk=1)
+>>> a3.headline
+'Third'
+>>> a3.pub_date
+datetime.date(2005, 8, 22)
+
+# Create an ArticleWithManyChanges.
+>>> a4 = subarticles4.ArticleWithManyChanges(headline='Fourth', section='Arts',
+... is_popular=True, pub_date=date(2005, 8, 22))
+>>> a4.save()
+
+# a4 inherits __repr__() from its parent model (ArticleWithRepr).
+>>> a4
+Fourth
+
+# Retrieve it again, to prove the fields have been saved.
+>>> a4 = subarticles4.get_object(pk=1)
+>>> a4.headline
+'Fourth'
+>>> a4.section
+'Arts'
+>>> a4.is_popular == True
+True
+>>> a4.pub_date
+datetime.date(2005, 8, 22)
+
+# Test get_list().
+>>> subarticles1.get_list()
+[<ArticleWithSection object>]
+>>> subarticles2.get_list()
+[<ArticleWithoutPubDate object>]
+>>> subarticles3.get_list()
+[<ArticleWithFieldOverride object>]
+>>> subarticles4.get_list()
+[Fourth]
+
+# Create a couple of ArticleWithChangedMeta objects.
+>>> a5 = subarticles5.ArticleWithChangedMeta(headline='A', pub_date=datetime(2005, 3, 1))
+>>> a5.save()
+>>> a6 = subarticles5.ArticleWithChangedMeta(headline='B', pub_date=datetime(2005, 4, 1))
+>>> a6.save()
+>>> a7 = subarticles5.ArticleWithChangedMeta(headline='C', pub_date=datetime(2005, 5, 1))
+>>> a7.save()
+
+# Ordering has been overridden, so objects are ordered
+# by headline ASC instead of pub_date DESC.
+>>> subarticles5.get_list()
+[A, B, C]
+"""