Changed all model unit tests to use __str__() instead of __repr__(). Also slightly changed related-object DoesNotExist exception message to use repr instead of str

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3075 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-06-04 00:23:51 +00:00
parent 55e453a09c
commit a5b7c29816
28 changed files with 341 additions and 336 deletions

View File

@ -198,7 +198,7 @@ class ForeignRelatedObjectsDescriptor(object):
setattr(obj, rel_field.name, None)
obj.save()
else:
raise rel_field.rel.to.DoesNotExist, "'%s' is not related to '%s'." % (obj, instance)
raise rel_field.rel.to.DoesNotExist, "%r is not related to %r." % (obj, instance)
remove.alters_data = True
def clear(self):
@ -712,7 +712,7 @@ class ManyToManyRel:
self.related_name = related_name
self.filter_interface = filter_interface
if limit_choices_to is None:
limit_choices_to = {}
limit_choices_to = {}
self.limit_choices_to = limit_choices_to
self.edit_inline = False
self.raw_id_admin = raw_id_admin

View File

@ -9,9 +9,10 @@ from django.db import models
class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline')
pub_date = models.DateTimeField()
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
# No articles are in the system yet.
@ -39,34 +40,34 @@ datetime.datetime(2005, 7, 28, 0, 0)
>>> a.headline = 'Area woman programs in Python'
>>> a.save()
# Article.objects.all() returns all the articles in the database.
# Article.objects.all() returns all the articles in the database.
>>> Article.objects.all()
[Area woman programs in Python]
[<Article: Area woman programs in Python>]
# Django provides a rich database lookup API.
>>> Article.objects.get(id__exact=1)
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.get(headline__startswith='Area woman')
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.get(pub_date__year=2005)
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7)
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
Area woman programs in Python
<Article: Area woman programs in Python>
# The "__exact" lookup type can be omitted, as a shortcut.
>>> Article.objects.get(id=1)
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.get(headline='Area woman programs in Python')
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.filter(pub_date__year=2005)
[Area woman programs in Python]
[<Article: Area woman programs in Python>]
>>> Article.objects.filter(pub_date__year=2004)
[]
>>> Article.objects.filter(pub_date__year=2005, pub_date__month=7)
[Area woman programs in Python]
[<Article: Area woman programs in Python>]
# Django raises an Article.DoesNotExist exception for get() if the parameters
# don't match any object.
@ -84,7 +85,7 @@ DoesNotExist: Article matching query does not exist.
# shortcut for primary-key exact lookups.
# The following is identical to articles.get(id=1).
>>> Article.objects.get(pk=1)
Area woman programs in Python
<Article: Area woman programs in Python>
# Model instances of the same type and same ID are considered equal.
>>> a = Article.objects.get(pk=1)
@ -222,7 +223,7 @@ datetime.datetime(2005, 7, 28, 0, 0)
>>> s1 = Article.objects.filter(id__exact=1)
>>> s2 = Article.objects.filter(id__exact=2)
>>> s1 | s2
[Area woman programs in Python, Second article]
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> s1 & s2
[]
@ -232,34 +233,34 @@ datetime.datetime(2005, 7, 28, 0, 0)
# You can get items using index and slice notation.
>>> Article.objects.all()[0]
Area woman programs in Python
<Article: Area woman programs in Python>
>>> Article.objects.all()[1:3]
[Second article, Third article]
[<Article: Second article>, <Article: Third article>]
>>> s3 = Article.objects.filter(id__exact=3)
>>> (s1 | s2 | s3)[::2]
[Area woman programs in Python, Third article]
[<Article: Area woman programs in Python>, <Article: Third article>]
# Slices (without step) are lazy:
>>> Article.objects.all()[0:5].filter()
[Area woman programs in Python, Second article, Third article, Fourth article, Article 6]
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>]
# Slicing again works:
>>> Article.objects.all()[0:5][0:2]
[Area woman programs in Python, Second article]
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> Article.objects.all()[0:5][:2]
[Area woman programs in Python, Second article]
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> Article.objects.all()[0:5][4:]
[Article 6]
[<Article: Article 6>]
>>> Article.objects.all()[0:5][5:]
[]
# Some more tests!
>>> Article.objects.all()[2:][0:2]
[Third article, Fourth article]
[<Article: Third article>, <Article: Fourth article>]
>>> Article.objects.all()[2:][:2]
[Third article, Fourth article]
[<Article: Third article>, <Article: Fourth article>]
>>> Article.objects.all()[2:][2:3]
[Article 6]
[<Article: Article 6>]
# Note that you can't use 'offset' without 'limit' (on some dbs), so this doesn't work:
>>> Article.objects.all()[2:]
@ -308,10 +309,10 @@ AttributeError: Manager isn't accessible via Article instances
# Bulk delete test: How many objects before and after the delete?
>>> Article.objects.all()
[Area woman programs in Python, Second article, Third article, Fourth article, Article 6, Default headline, Article 7, Updated article 8]
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
>>> Article.objects.filter(id__lte=4).delete()
>>> Article.objects.all()
[Article 6, Default headline, Article 7, Updated article 8]
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
"""

View File

@ -20,7 +20,7 @@ class Person(models.Model):
name = models.CharField(maxlength=20)
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """

View File

@ -12,7 +12,7 @@ class Person(models.Model):
first_name = models.CharField(maxlength=30, db_column='firstname')
last_name = models.CharField(maxlength=30, db_column='last')
def __repr__(self):
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
API_TESTS = """
@ -24,13 +24,13 @@ API_TESTS = """
1
>>> Person.objects.all()
[John Smith]
[<Person: John Smith>]
>>> Person.objects.filter(first_name__exact='John')
[John Smith]
[<Person: John Smith>]
>>> Person.objects.get(first_name__exact='John')
John Smith
<Person: John Smith>
>>> Person.objects.filter(firstname__exact='John')
Traceback (most recent call last):

View File

@ -23,7 +23,7 @@ class Person(models.Model):
fun = models.BooleanField()
objects = PersonManager()
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
# An example of a custom manager that sets get_query_set().
@ -39,7 +39,7 @@ class Book(models.Model):
published_objects = PublishedBookManager()
authors = models.ManyToManyField(Person, related_name='books')
def __repr__(self):
def __str__(self):
return self.title
# An example of providing multiple custom managers.
@ -55,7 +55,7 @@ class Car(models.Model):
cars = models.Manager()
fast_cars = FastCarManager()
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
@ -64,7 +64,7 @@ API_TESTS = """
>>> p2 = Person(first_name='Droopy', last_name='Dog', fun=False)
>>> p2.save()
>>> Person.objects.get_fun_people()
[Bugs Bunny]
[<Person: Bugs Bunny>]
# The RelatedManager used on the 'books' descriptor extends the default manager
>>> from modeltests.custom_managers.models import PublishedBookManager
@ -89,19 +89,19 @@ AttributeError: type object 'Book' has no attribute 'objects'
True
>>> Book.published_objects.all()
[How to program]
[<Book: How to program>]
>>> c1 = Car(name='Corvette', mileage=21, top_speed=180)
>>> c1.save()
>>> c2 = Car(name='Neon', mileage=31, top_speed=100)
>>> c2.save()
>>> Car.cars.order_by('name')
[Corvette, Neon]
[<Car: Corvette>, <Car: Neon>]
>>> Car.fast_cars.all()
[Corvette]
[<Car: Corvette>]
# 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".
>>> Car._default_manager.order_by('name')
[Corvette, Neon]
[<Car: Corvette>, <Car: Neon>]
"""

View File

@ -11,16 +11,16 @@ class Article(models.Model):
headline = models.CharField(maxlength=100)
pub_date = models.DateField()
def __repr__(self):
def __str__(self):
return self.headline
def was_published_today(self):
return self.pub_date == datetime.date.today()
def get_articles_from_same_day_1(self):
def articles_from_same_day_1(self):
return Article.objects.filter(pub_date=self.pub_date).exclude(id=self.id)
def get_articles_from_same_day_2(self):
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.
@ -47,12 +47,12 @@ API_TESTS = """
# Test the custom methods.
>>> a.was_published_today()
False
>>> a.get_articles_from_same_day_1()
[Beatles reunite]
>>> a.get_articles_from_same_day_2()
[Beatles reunite]
>>> b.get_articles_from_same_day_1()
[Area man programs in Python]
>>> b.get_articles_from_same_day_2()
[Area man programs in Python]
>>> a.articles_from_same_day_1()
[<Article: Beatles reunite>]
>>> a.articles_from_same_day_2()
[<Article: Beatles reunite>]
>>> b.articles_from_same_day_1()
[<Article: Area man programs in Python>]
>>> b.articles_from_same_day_2()
[<Article: Area man programs in Python>]
"""

View File

@ -14,7 +14,7 @@ class Employee(models.Model):
class Meta:
ordering = ('last_name', 'first_name')
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Business(models.Model):
@ -23,24 +23,24 @@ class Business(models.Model):
class Meta:
verbose_name_plural = 'businesses'
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
>>> dan = Employee(employee_code='ABC123', first_name='Dan', last_name='Jones')
>>> dan.save()
>>> Employee.objects.all()
[Dan Jones]
[<Employee: Dan Jones>]
>>> fran = Employee(employee_code='XYZ456', first_name='Fran', last_name='Bones')
>>> fran.save()
>>> Employee.objects.all()
[Fran Bones, Dan Jones]
[<Employee: Fran Bones>, <Employee: Dan Jones>]
>>> Employee.objects.get(pk='ABC123')
Dan Jones
<Employee: Dan Jones>
>>> Employee.objects.get(pk='XYZ456')
Fran Bones
<Employee: Fran Bones>
>>> Employee.objects.get(pk='foo')
Traceback (most recent call last):
...
@ -48,43 +48,43 @@ DoesNotExist: Employee matching query does not exist.
# Use the name of the primary key, rather than pk.
>>> Employee.objects.get(employee_code__exact='ABC123')
Dan Jones
<Employee: Dan Jones>
# Fran got married and changed her last name.
>>> fran = Employee.objects.get(pk='XYZ456')
>>> fran.last_name = 'Jones'
>>> fran.save()
>>> Employee.objects.filter(last_name__exact='Jones')
[Dan Jones, Fran Jones]
[<Employee: Dan Jones>, <Employee: Fran Jones>]
>>> Employee.objects.in_bulk(['ABC123', 'XYZ456'])
{'XYZ456': Fran Jones, 'ABC123': Dan Jones}
{'XYZ456': <Employee: Fran Jones>, 'ABC123': <Employee: Dan Jones>}
>>> b = Business(name='Sears')
>>> b.save()
>>> b.employees.add(dan, fran)
>>> b.employees.all()
[Dan Jones, Fran Jones]
[<Employee: Dan Jones>, <Employee: Fran Jones>]
>>> fran.business_set.all()
[Sears]
[<Business: Sears>]
>>> Business.objects.in_bulk(['Sears'])
{'Sears': Sears}
{'Sears': <Business: Sears>}
>>> Business.objects.filter(name__exact='Sears')
[Sears]
[<Business: Sears>]
>>> Business.objects.filter(pk='Sears')
[Sears]
[<Business: Sears>]
# Queries across tables, involving primary key
>>> Employee.objects.filter(business__name__exact='Sears')
[Dan Jones, Fran Jones]
[<Employee: Dan Jones>, <Employee: Fran Jones>]
>>> Employee.objects.filter(business__pk='Sears')
[Dan Jones, Fran Jones]
[<Employee: Dan Jones>, <Employee: Fran Jones>]
>>> Business.objects.filter(employees__employee_code__exact='ABC123')
[Sears]
[<Business: Sears>]
>>> Business.objects.filter(employees__pk='ABC123')
[Sears]
[<Business: Sears>]
>>> Business.objects.filter(employees__first_name__startswith='Fran')
[Sears]
[<Business: Sears>]
"""

View File

@ -17,7 +17,7 @@ class Article(models.Model):
class Meta:
get_latest_by = 'pub_date'
def __repr__(self):
def __str__(self):
return self.headline
class Person(models.Model):
@ -26,7 +26,7 @@ class Person(models.Model):
# Note that this model doesn't have "get_latest_by" set.
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
@ -49,19 +49,19 @@ DoesNotExist: Article matching query does not exist.
# Get the latest Article.
>>> Article.objects.latest()
Article 4
<Article: Article 4>
# Get the latest Article that matches certain filters.
>>> Article.objects.filter(pub_date__lt=datetime(2005, 7, 27)).latest()
Article 1
<Article: Article 1>
# Pass a custom field name to latest() to change the field that's used to
# determine the latest object.
>>> Article.objects.latest('expire_date')
Article 1
<Article: Article 1>
>>> Article.objects.filter(pub_date__gt=datetime(2005, 7, 26)).latest('expire_date')
Article 3
<Article: Article 3>
# You can still use latest() with a model that doesn't have "get_latest_by"
# set -- just pass in the field name manually.
@ -75,5 +75,5 @@ Traceback (most recent call last):
AssertionError: latest() requires either a field_name parameter or 'get_latest_by' in the model
>>> Person.objects.latest('birthday')
Stephanie
<Person: Stephanie>
"""

View File

@ -12,7 +12,7 @@ class Article(models.Model):
class Meta:
ordering = ('-pub_date', 'headline')
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
@ -61,9 +61,9 @@ Article 4
# in_bulk() takes a list of IDs and returns a dictionary mapping IDs
# to objects.
>>> Article.objects.in_bulk([1, 2])
{1: Article 1, 2: Article 2}
{1: <Article: Article 1>, 2: <Article: Article 2>}
>>> Article.objects.in_bulk([3])
{3: Article 3}
{3: <Article: Article 3>}
>>> Article.objects.in_bulk([1000])
{}
>>> Article.objects.in_bulk([])
@ -125,55 +125,55 @@ True
# 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.
>>> a1.get_next_by_pub_date()
Article 2
<Article: Article 2>
>>> a2.get_next_by_pub_date()
Article 3
<Article: Article 3>
>>> a3.get_next_by_pub_date()
Article 7
<Article: Article 7>
>>> a4.get_next_by_pub_date()
Article 6
<Article: Article 6>
>>> a5.get_next_by_pub_date()
Traceback (most recent call last):
...
DoesNotExist: Article matching query does not exist.
>>> a6.get_next_by_pub_date()
Article 5
<Article: Article 5>
>>> a7.get_next_by_pub_date()
Article 4
<Article: Article 4>
>>> a7.get_previous_by_pub_date()
Article 3
<Article: Article 3>
>>> a6.get_previous_by_pub_date()
Article 4
<Article: Article 4>
>>> a5.get_previous_by_pub_date()
Article 6
<Article: Article 6>
>>> a4.get_previous_by_pub_date()
Article 7
<Article: Article 7>
>>> a3.get_previous_by_pub_date()
Article 2
<Article: Article 2>
>>> a2.get_previous_by_pub_date()
Article 1
<Article: Article 1>
# Underscores and percent signs have special meaning in the underlying
# database library, but Django handles the quoting of them automatically.
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
>>> a8.save()
>>> Article.objects.filter(headline__startswith='Article')
[Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
[<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>]
>>> Article.objects.filter(headline__startswith='Article_')
[Article_ with underscore]
[<Article: Article_ with underscore>]
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
>>> a9.save()
>>> Article.objects.filter(headline__startswith='Article')
[Article% with percent sign, Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
[<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>]
>>> Article.objects.filter(headline__startswith='Article%')
[Article% with percent sign]
[<Article: Article% with percent sign>]
# exclude() is the opposite of filter() when doing lookups:
>>> Article.objects.filter(headline__contains='Article').exclude(headline__contains='with')
[Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
[<Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
>>> Article.objects.exclude(headline__startswith="Article_")
[Article% with percent sign, Article 5, Article 6, Article 4, Article 2, Article 3, Article 7, Article 1]
[<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>]
>>> Article.objects.exclude(headline="Article 7")
[Article% with percent sign, Article_ with underscore, Article 5, Article 6, Article 4, Article 2, Article 3, Article 1]
[<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>]
"""

View File

@ -16,14 +16,14 @@ class Reporter(models.Model):
first_name = models.CharField(maxlength=30)
last_name = models.CharField(maxlength=30)
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Article(models.Model):
headline = models.CharField(maxlength=100)
pub_date = models.DateField()
def __repr__(self):
def __str__(self):
return self.headline
class Writer(models.Model):
@ -31,8 +31,8 @@ class Writer(models.Model):
article = models.ForeignKey(Article)
position = models.CharField(maxlength=100)
def __repr__(self):
return '%r (%s)' % (self.reporter, self.position)
def __str__(self):
return '%s (%s)' % (self.reporter, self.position)
API_TESTS = """
# Create a few Reporters.
@ -54,15 +54,15 @@ API_TESTS = """
# Play around with the API.
>>> a.writer_set.select_related().order_by('-position')
[John Smith (Main writer), Jane Doe (Contributor)]
[<Writer: John Smith (Main writer)>, <Writer: Jane Doe (Contributor)>]
>>> w1.reporter
John Smith
<Reporter: John Smith>
>>> w2.reporter
Jane Doe
<Reporter: Jane Doe>
>>> w1.article
This is a test
<Article: This is a test>
>>> w2.article
This is a test
<Article: This is a test>
>>> r1.writer_set.all()
[John Smith (Main writer)]
[<Writer: John Smith (Main writer)>]
"""

View File

@ -14,7 +14,7 @@ class Category(models.Model):
class Meta:
ordering = ('name',)
def __repr__(self):
def __str__(self):
return self.name
class Article(models.Model):
@ -25,7 +25,7 @@ class Article(models.Model):
class Meta:
ordering = ('pub_date',)
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
@ -51,29 +51,29 @@ API_TESTS = """
>>> a2.secondary_categories.add(c4)
>>> a1.primary_categories.all()
[Crime, News]
[<Category: Crime>, <Category: News>]
>>> a2.primary_categories.all()
[News, Sports]
[<Category: News>, <Category: Sports>]
>>> a1.secondary_categories.all()
[Life]
[<Category: Life>]
>>> c1.primary_article_set.all()
[Area man runs]
[<Article: Area man runs>]
>>> c1.secondary_article_set.all()
[]
>>> c2.primary_article_set.all()
[Area man steals, Area man runs]
[<Article: Area man steals>, <Article: Area man runs>]
>>> c2.secondary_article_set.all()
[]
>>> c3.primary_article_set.all()
[Area man steals]
[<Article: Area man steals>]
>>> c3.secondary_article_set.all()
[]
>>> c4.primary_article_set.all()
[]
>>> c4.secondary_article_set.all()
[Area man steals, Area man runs]
[<Article: Area man steals>, <Article: Area man runs>]
"""

View File

@ -19,7 +19,7 @@ class Person(models.Model):
friends = models.ManyToManyField('self')
idols = models.ManyToManyField('self', symmetrical=False, related_name='stalkers')
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
@ -41,37 +41,37 @@ API_TESTS = """
# Who is friends with Anne?
>>> a.friends.all()
[Bill, Chuck, David]
[<Person: Bill>, <Person: Chuck>, <Person: David>]
# Who is friends with Bill?
>>> b.friends.all()
[Anne]
[<Person: Anne>]
# Who is friends with Chuck?
>>> c.friends.all()
[Anne, David]
[<Person: Anne>, <Person: David>]
# Who is friends with David?
>>> d.friends.all()
[Anne, Chuck]
[<Person: Anne>, <Person: Chuck>]
# Bill is already friends with Anne - add Anne again, but in the reverse direction
>>> b.friends.add(a)
# Who is friends with Anne?
>>> a.friends.all()
[Bill, Chuck, David]
[<Person: Bill>, <Person: Chuck>, <Person: David>]
# Who is friends with Bill?
>>> b.friends.all()
[Anne]
[<Person: Anne>]
# Remove Anne from Bill's friends
>>> b.friends.remove(a)
# Who is friends with Anne?
>>> a.friends.all()
[Chuck, David]
[<Person: Chuck>, <Person: David>]
# Who is friends with Bill?
>>> b.friends.all()
@ -87,11 +87,11 @@ API_TESTS = """
# Reverse relationships should also be gone
# Who is friends with Chuck?
>>> c.friends.all()
[David]
[<Person: David>]
# Who is friends with David?
>>> d.friends.all()
[Chuck]
[<Person: Chuck>]
# Add some idols in the direction of field definition
@ -106,27 +106,27 @@ API_TESTS = """
# Who are Anne's idols?
>>> a.idols.all()
[Bill, Chuck, David]
[<Person: Bill>, <Person: Chuck>, <Person: David>]
# Who is stalking Anne?
>>> a.stalkers.all()
[Bill]
[<Person: Bill>]
# Who are Bill's idols?
>>> b.idols.all()
[Anne]
[<Person: Anne>]
# Who is stalking Bill?
>>> b.stalkers.all()
[Anne]
[<Person: Anne>]
# Who are Chuck's idols?
>>> c.idols.all()
[David]
[<Person: David>]
# Who is stalking Chuck?
>>> c.stalkers.all()
[Anne]
[<Person: Anne>]
# Who are David's idols?
>>> d.idols.all()
@ -134,40 +134,40 @@ API_TESTS = """
# Who is stalking David
>>> d.stalkers.all()
[Anne, Chuck]
[<Person: Anne>, <Person: Chuck>]
# Bill is already being stalked by Anne - add Anne again, but in the reverse direction
>>> b.stalkers.add(a)
# Who are Anne's idols?
>>> a.idols.all()
[Bill, Chuck, David]
[<Person: Bill>, <Person: Chuck>, <Person: David>]
# Who is stalking Anne?
[Bill]
[<Person: Bill>]
# Who are Bill's idols
>>> b.idols.all()
[Anne]
[<Person: Anne>]
# Who is stalking Bill?
>>> b.stalkers.all()
[Anne]
[<Person: Anne>]
# Remove Anne from Bill's list of stalkers
>>> b.stalkers.remove(a)
# Who are Anne's idols?
>>> a.idols.all()
[Chuck, David]
[<Person: Chuck>, <Person: David>]
# Who is stalking Anne?
>>> a.stalkers.all()
[Bill]
[<Person: Bill>]
# Who are Bill's idols?
>>> b.idols.all()
[Anne]
[<Person: Anne>]
# Who is stalking Bill?
>>> b.stalkers.all()
@ -187,6 +187,6 @@ API_TESTS = """
# Who is friends with David?
>>> d.stalkers.all()
[Chuck]
[<Person: Chuck>]
"""

View File

@ -16,7 +16,7 @@ class Category(models.Model):
name = models.CharField(maxlength=20)
parent = models.ForeignKey('self', null=True, related_name='child_set')
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
@ -27,14 +27,14 @@ API_TESTS = """
>>> c.save()
>>> r.child_set.all()
[Child category]
[<Category: Child category>]
>>> r.child_set.get(name__startswith='Child')
Child category
<Category: Child category>
>>> print r.parent
None
>>> c.child_set.all()
[]
>>> c.parent
Root category
<Category: Root category>
"""

View File

@ -14,7 +14,7 @@ class Person(models.Model):
mother = models.ForeignKey('self', null=True, related_name='mothers_child_set')
father = models.ForeignKey('self', null=True, related_name='fathers_child_set')
def __repr__(self):
def __str__(self):
return self.full_name
API_TESTS = """
@ -29,13 +29,13 @@ API_TESTS = """
>>> kid.save()
>>> kid.mother
Jane Smith
<Person: Jane Smith>
>>> kid.father
John Smith Senior
<Person: John Smith Senior>
>>> dad.fathers_child_set.all()
[John Smith Junior]
[<Person: John Smith Junior>]
>>> mom.mothers_child_set.all()
[John Smith Junior]
[<Person: John Smith Junior>]
>>> kid.mothers_child_set.all()
[]
>>> kid.fathers_child_set.all()

View File

@ -10,7 +10,7 @@ class Musician(models.Model):
first_name = models.CharField(maxlength=30)
last_name = models.CharField(maxlength=30)
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Album(models.Model):
@ -18,7 +18,7 @@ class Album(models.Model):
musician = models.ForeignKey(Musician)
release_date = models.DateField(blank=True, null=True)
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """
@ -35,7 +35,7 @@ API_TESTS = """
# Verify it worked.
>>> Musician.objects.all()
[Ella Fitzgerald]
[<Musician: Ella Fitzgerald>]
>>> [m1] == list(Musician.objects.all())
True
@ -69,9 +69,9 @@ True
# Verify it worked.
>>> Album.objects.all()
[Ella and Basie]
[<Album: Ella and Basie>]
>>> Album.objects.get().musician
Ella Fitzgerald
<Musician: Ella Fitzgerald>
# Create an Album with a release_date.
>>> data = MultiValueDict({'name': ['Ultimate Ella'], 'musician': ['1'], 'release_date': ['2005-02-13']})
@ -82,10 +82,10 @@ Ella Fitzgerald
# Verify it worked.
>>> Album.objects.order_by('name')
[Ella and Basie, Ultimate Ella]
[<Album: Ella and Basie>, <Album: Ultimate Ella>]
>>> a2 = Album.objects.get(pk=2)
>>> a2
Ultimate Ella
<Album: Ultimate Ella>
>>> a2.release_date
datetime.date(2005, 2, 13)
"""

View File

@ -12,7 +12,7 @@ from django.db import models
class Publication(models.Model):
title = models.CharField(maxlength=30)
def __repr__(self):
def __str__(self):
return self.title
class Meta:
@ -22,7 +22,7 @@ class Article(models.Model):
headline = models.CharField(maxlength=100)
publications = models.ManyToManyField(Publication)
def __repr__(self):
def __str__(self):
return self.headline
class Meta:
@ -58,29 +58,29 @@ API_TESTS = """
# Article objects have access to their related Publication objects.
>>> a1.publications.all()
[The Python Journal]
[<Publication: The Python Journal>]
>>> a2.publications.all()
[Highlights for Children, Science News, Science Weekly, The Python Journal]
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
# Publication objects have access to their related Article objects.
>>> p2.article_set.all()
[NASA uses Python]
[<Article: NASA uses Python>]
>>> p1.article_set.all()
[Django lets you build Web apps easily, NASA uses Python]
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Publication.objects.get(id=4).article_set.all()
[NASA uses Python]
[<Article: NASA uses Python>]
# We can perform kwarg queries across m2m relationships
>>> Article.objects.filter(publications__id__exact=1)
[Django lets you build Web apps easily, NASA uses Python]
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications__pk=1)
[Django lets you build Web apps easily, NASA uses Python]
[<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications__title__startswith="Science")
[NASA uses Python, NASA uses Python]
[<Article: NASA uses Python>, <Article: NASA uses Python>]
>>> Article.objects.filter(publications__title__startswith="Science").distinct()
[NASA uses Python]
[<Article: NASA uses Python>]
# The count() function respects distinct() as well.
>>> Article.objects.filter(publications__title__startswith="Science").count()
@ -92,23 +92,23 @@ API_TESTS = """
# Reverse m2m queries are supported (i.e., starting at the table that doesn't
# have a ManyToManyField).
>>> Publication.objects.filter(id__exact=1)
[The Python Journal]
[<Publication: The Python Journal>]
>>> Publication.objects.filter(pk=1)
[The Python Journal]
[<Publication: The Python Journal>]
>>> Publication.objects.filter(article__headline__startswith="NASA")
[Highlights for Children, Science News, Science Weekly, The Python Journal]
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]
>>> Publication.objects.filter(article__id__exact=1)
[The Python Journal]
[<Publication: The Python Journal>]
>>> Publication.objects.filter(article__pk=1)
[The Python Journal]
[<Publication: The Python Journal>]
# If we delete a Publication, its Articles won't be able to access it.
>>> p1.delete()
>>> Publication.objects.all()
[Highlights for Children, Science News, Science Weekly]
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]
>>> a1 = Article.objects.get(pk=1)
>>> a1.publications.all()
[]
@ -116,7 +116,7 @@ API_TESTS = """
# If we delete an Article, its Publications won't be able to access it.
>>> a2.delete()
>>> Article.objects.all()
[Django lets you build Web apps easily]
[<Article: Django lets you build Web apps easily>]
>>> p2.article_set.all()
[]
@ -125,22 +125,22 @@ API_TESTS = """
>>> a4.save()
>>> p2.article_set.add(a4)
>>> p2.article_set.all()
[NASA finds intelligent life on Earth]
[<Article: NASA finds intelligent life on Earth>]
>>> a4.publications.all()
[Science News]
[<Publication: Science News>]
# Adding via the other end using keywords
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
>>> p2.article_set.all()
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
>>> a5 = p2.article_set.all()[1]
>>> a5.publications.all()
[Science News]
[<Publication: Science News>]
# Removing publication from an article:
>>> a4.publications.remove(p2)
>>> p2.article_set.all()
[Oxygen-free diet works wonders]
[<Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[]
@ -154,33 +154,33 @@ API_TESTS = """
# Relation sets can be assigned. Assignment clears any existing set members
>>> p2.article_set = [a4, a5]
>>> p2.article_set.all()
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[Science News]
[<Publication: Science News>]
>>> a4.publications = [p3]
>>> p2.article_set.all()
[Oxygen-free diet works wonders]
[<Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[Science Weekly]
[<Publication: Science Weekly>]
# Relation sets can be cleared:
>>> p2.article_set.clear()
>>> p2.article_set.all()
[]
>>> a4.publications.all()
[Science Weekly]
[<Publication: Science Weekly>]
# And you can clear from the other end
>>> p2.article_set.add(a4, a5)
>>> p2.article_set.all()
[NASA finds intelligent life on Earth, Oxygen-free diet works wonders]
[<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]
>>> a4.publications.all()
[Science News, Science Weekly]
[<Publication: Science News>, <Publication: Science Weekly>]
>>> a4.publications.clear()
>>> a4.publications.all()
[]
>>> p2.article_set.all()
[Oxygen-free diet works wonders]
[<Article: Oxygen-free diet works wonders>]
# Recreate the article and Publication we just deleted.
>>> p1 = Publication(id=None, title='The Python Journal')
@ -192,22 +192,22 @@ API_TESTS = """
# Bulk delete some Publications - references to deleted publications should go
>>> Publication.objects.filter(title__startswith='Science').delete()
>>> Publication.objects.all()
[Highlights for Children, The Python Journal]
[<Publication: Highlights for Children>, <Publication: The Python Journal>]
>>> Article.objects.all()
[Django lets you build Web apps easily, NASA finds intelligent life on Earth, NASA uses Python, Oxygen-free diet works wonders]
[<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>]
>>> a2.publications.all()
[The Python Journal]
[<Publication: The Python Journal>]
# Bulk delete some articles - references to deleted objects should go
>>> q = Article.objects.filter(headline__startswith='Django')
>>> print q
[Django lets you build Web apps easily]
[<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
>>> print q
[]
>>> p1.article_set.all()
[NASA uses Python]
[<Article: NASA uses Python>]
"""

View File

@ -11,7 +11,7 @@ class Reporter(models.Model):
last_name = models.CharField(maxlength=30)
email = models.EmailField()
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Article(models.Model):
@ -19,7 +19,7 @@ class Article(models.Model):
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter)
def __repr__(self):
def __str__(self):
return self.headline
class Meta:
@ -42,7 +42,7 @@ API_TESTS = """
1
>>> a.reporter
John Smith
<Reporter: John Smith>
# Article objects have access to their related Reporter objects.
>>> r = a.reporter
@ -52,7 +52,7 @@ John Smith
# Create an Article via the Reporter object.
>>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(2005, 7, 29))
>>> new_article
John's second story
<Article: John's second story>
>>> new_article.reporter.id
1
@ -62,43 +62,43 @@ John's second story
>>> new_article2.reporter.id
1
>>> r.article_set.all()
[John's second story, Paul's story, This is a test]
[<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.
>>> r2.article_set.add(new_article2)
>>> new_article2.reporter.id
2
>>> r.article_set.all()
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
>>> r2.article_set.all()
[Paul's story]
[<Article: Paul's story>]
# Assign the article to the reporter directly using the descriptor
>>> new_article2.reporter = r
>>> new_article2.save()
>>> new_article2.reporter
John Smith
<Reporter: John Smith>
>>> new_article2.reporter.id
1
>>> r.article_set.all()
[John's second story, Paul's story, This is a test]
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]
>>> r2.article_set.all()
[]
# Set the article back again using set descriptor.
>>> r2.article_set = [new_article, new_article2]
>>> r.article_set.all()
[This is a test]
[<Article: This is a test>]
>>> r2.article_set.all()
[John's second story, Paul's story]
[<Article: John's second story>, <Article: Paul's story>]
# Funny case - assignment notation can only go so far; because the
# Funny case - assignment notation can only go so far; because the
# ForeignKey cannot be null, existing members of the set must remain
>>> r.article_set = [new_article]
>>> r.article_set.all()
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
>>> r2.article_set.all()
[Paul's story]
[<Article: Paul's story>]
# Reporter cannot be null - there should not be a clear or remove method
>>> hasattr(r2.article_set, 'remove')
@ -108,10 +108,10 @@ False
# Reporter objects have access to their related Article objects.
>>> r.article_set.all()
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
>>> r.article_set.filter(headline__startswith='This')
[This is a test]
[<Article: This is a test>]
>>> r.article_set.count()
2
@ -121,24 +121,24 @@ False
# Get articles by id
>>> Article.objects.filter(id__exact=1)
[This is a test]
[<Article: This is a test>]
>>> Article.objects.filter(pk=1)
[This is a test]
[<Article: This is a test>]
# Query on an article property
>>> Article.objects.filter(headline__startswith='This')
[This is a test]
[<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".
>>> Article.objects.filter(reporter__first_name__exact='John')
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
# Query twice over the related field.
>>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
# The underlying query only makes one join when a related table is referenced twice.
>>> query = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith')
@ -148,13 +148,13 @@ False
# The automatically joined table has a predictable name.
>>> Article.objects.filter(reporter__first_name__exact='John').extra(where=["many_to_one_article__reporter.last_name='Smith'"])
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
# Find all Articles for the Reporter whose ID is 1.
>>> Article.objects.filter(reporter__id__exact=1)
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
>>> Article.objects.filter(reporter__pk=1)
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
# You need two underscores between "reporter" and "id" -- not one.
>>> Article.objects.filter(reporter_id__exact=1)
@ -170,7 +170,7 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
# "pk" shortcut syntax works in a related context, too.
>>> Article.objects.filter(reporter__pk=1)
[John's second story, This is a test]
[<Article: John's second story>, <Article: This is a test>]
# You can also instantiate an Article by passing
# the Reporter's ID instead of a Reporter object.
@ -179,31 +179,31 @@ TypeError: Cannot resolve keyword 'reporter_id' into field
>>> a3.reporter.id
1
>>> a3.reporter
John Smith
<Reporter: John Smith>
# Similarly, the reporter ID can be a string.
>>> a4 = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporter_id="1")
>>> a4.save()
>>> a4.reporter
John Smith
<Reporter: John Smith>
# Reporters can be queried
>>> Reporter.objects.filter(id__exact=1)
[John Smith]
[<Reporter: John Smith>]
>>> Reporter.objects.filter(pk=1)
[John Smith]
[<Reporter: John Smith>]
>>> Reporter.objects.filter(first_name__startswith='John')
[John Smith]
[<Reporter: John Smith>]
# Reporters can query in opposite direction of ForeignKey definition
>>> Reporter.objects.filter(article__id__exact=1)
[John Smith]
[<Reporter: John Smith>]
>>> Reporter.objects.filter(article__pk=1)
[John Smith]
[<Reporter: John Smith>]
>>> Reporter.objects.filter(article__headline__startswith='This')
[John Smith, John Smith, John Smith]
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
[John Smith]
[<Reporter: John Smith>]
# Counting in the opposite direction works in conjunction with distinct()
>>> Reporter.objects.filter(article__headline__startswith='This').count()
@ -213,20 +213,20 @@ John Smith
# Queries can go round in circles.
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
[John Smith, John Smith, John Smith, John Smith]
[<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct()
[John Smith]
[<Reporter: John Smith>]
# If you delete a reporter, his articles will be deleted.
>>> Article.objects.all()
[John's second story, Paul's story, This is a test, This is a test, This is a test]
[<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
>>> Reporter.objects.order_by('first_name')
[John Smith, Paul Jones]
[<Reporter: John Smith>, <Reporter: Paul Jones>]
>>> r2.delete()
>>> Article.objects.all()
[John's second story, This is a test, This is a test, This is a test]
[<Article: John's second story>, <Article: This is a test>, <Article: This is a test>, <Article: This is a test>]
>>> Reporter.objects.order_by('first_name')
[John Smith]
[<Reporter: John Smith>]
# Deletes using a join in the query
>>> Reporter.objects.filter(article__headline__startswith='This').delete()

View File

@ -10,19 +10,19 @@ from django.db import models
class Reporter(models.Model):
name = models.CharField(maxlength=30)
def __repr__(self):
def __str__(self):
return self.name
class Article(models.Model):
headline = models.CharField(maxlength=100)
reporter = models.ForeignKey(Reporter, null=True)
def __repr__(self):
return self.headline
class Meta:
ordering = ('headline',)
def __str__(self):
return self.headline
API_TESTS = """
# Create a Reporter.
>>> r = Reporter(name='John Smith')
@ -36,7 +36,7 @@ API_TESTS = """
1
>>> a.reporter
John Smith
<Reporter: John Smith>
# Article objects have access to their related Reporter objects.
>>> r = a.reporter
@ -44,15 +44,15 @@ John Smith
# Create an Article via the Reporter object.
>>> a2 = r.article_set.create(headline="Second")
>>> a2
Second
<Article: Second>
>>> a2.reporter.id
1
# Reporter objects have access to their related Article objects.
>>> r.article_set.all()
[First, Second]
[<Article: First>, <Article: Second>]
>>> r.article_set.filter(headline__startswith='Fir')
[First]
[<Article: First>]
>>> r.article_set.count()
2
@ -78,47 +78,47 @@ None
# To retrieve the articles with no reporters set, use "reporter__isnull=True".
>>> Article.objects.filter(reporter__isnull=True)
[Third]
[<Article: Third>]
# Set the reporter for the Third article
>>> r.article_set.add(a3)
>>> r.article_set.all()
[First, Second, Third]
[<Article: First>, <Article: Second>, <Article: Third>]
# Remove an article from the set, and check that it was removed.
>>> r.article_set.remove(a3)
>>> r.article_set.all()
[First, Second]
[<Article: First>, <Article: Second>]
>>> Article.objects.filter(reporter__isnull=True)
[Third]
[<Article: Third>]
# Create another article and reporter
>>> r2 = Reporter(name='Paul Jones')
>>> r2.save()
>>> a4 = r2.article_set.create(headline='Fourth')
>>> r2.article_set.all()
[Fourth]
[<Article: Fourth>]
# Try to remove a4 from a set it does not belong to
>>> r.article_set.remove(a4)
Traceback (most recent call last):
...
DoesNotExist: 'Article object' is not related to 'Reporter object'.
DoesNotExist: <Article: Fourth> is not related to <Reporter: John Smith>.
>>> r2.article_set.all()
[Fourth]
[<Article: Fourth>]
# Use descriptor assignment to allocate ForeignKey. Null is legal, so
# existing members of set that are not in the assignment set are set null
>>> r2.article_set = [a2, a3]
>>> r2.article_set.all()
[Second, Third]
[<Article: Second>, <Article: Third>]
# Clear the rest of the set
>>> r.article_set.clear()
>>> r.article_set.all()
[]
>>> Article.objects.filter(reporter__isnull=True)
[First, Fourth]
[<Article: First>, <Article: Fourth>]
"""

View File

@ -10,20 +10,20 @@ class Place(models.Model):
name = models.CharField(maxlength=50)
address = models.CharField(maxlength=80)
def __repr__(self):
def __str__(self):
return "%s the place" % self.name
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
def __repr__(self):
def __str__(self):
return "%s the restaurant" % self.name
class ItalianRestaurant(Restaurant):
serves_gnocchi = models.BooleanField()
def __repr__(self):
def __str__(self):
return "%s the italian restaurant" % self.name
API_TESTS = """

View File

@ -12,7 +12,7 @@ class Place(models.Model):
name = models.CharField(maxlength=50)
address = models.CharField(maxlength=80)
def __repr__(self):
def __str__(self):
return "%s the place" % self.name
class Restaurant(models.Model):
@ -20,15 +20,15 @@ class Restaurant(models.Model):
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
def __repr__(self):
def __str__(self):
return "%s the restaurant" % self.place.name
class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant)
name = models.CharField(maxlength=50)
def __repr__(self):
return "%s the waiter at %r" % (self.name, self.restaurant)
def __str__(self):
return "%s the waiter at %s" % (self.name, self.restaurant)
API_TESTS = """
# Create a couple of Places.
@ -43,11 +43,11 @@ API_TESTS = """
# A Restaurant can access its place.
>>> r.place
Demon Dogs the place
<Place: Demon Dogs the place>
# A Place can access its restaurant, if available.
>>> p1.restaurant
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
# p2 doesn't have an associated restaurant.
>>> p2.restaurant
@ -60,69 +60,69 @@ DoesNotExist: Restaurant matching query does not exist.
>>> r.place = p2
>>> r.save()
>>> p2.restaurant
Ace Hardware the restaurant
<Restaurant: Ace Hardware the restaurant>
>>> r.place
Ace Hardware the place
<Place: Ace Hardware the place>
# Set the place back again, using assignment in the reverse direction
# Need to reget restaurant object first, because the reverse set
# Need to reget restaurant object first, because the reverse set
# can't update the existing restaurant instance
>>> p1.restaurant = r
>>> r.save()
>>> p1.restaurant
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> r = Restaurant.objects.get(pk=1)
>>> r.place
Demon Dogs the place
<Place: Demon Dogs the place>
# Restaurant.objects.all() just returns the Restaurants, not the Places.
# Note that there are two restaurants - Ace Hardware the Restaurant was created
# in the call to r.place = p2. This means there are multiple restaurants referencing
# in the call to r.place = p2. This means there are multiple restaurants referencing
# a single place...
>>> Restaurant.objects.all()
[Demon Dogs the restaurant, Ace Hardware the restaurant]
[<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]
# Place.objects.all() returns all Places, regardless of whether they have
# Restaurants.
>>> Place.objects.order_by('name')
[Ace Hardware the place, Demon Dogs the place]
[<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]
>>> Restaurant.objects.get(place__id__exact=1)
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.get(pk=1)
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.get(place__exact=1)
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.get(place__pk=1)
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> Restaurant.objects.get(place__name__startswith="Demon")
Demon Dogs the restaurant
<Restaurant: Demon Dogs the restaurant>
>>> Place.objects.get(id__exact=1)
Demon Dogs the place
<Place: Demon Dogs the place>
>>> Place.objects.get(pk=1)
Demon Dogs the place
<Place: Demon Dogs the place>
>>> Place.objects.get(restaurant__place__exact=1)
Demon Dogs the place
<Place: Demon Dogs the place>
>>> Place.objects.get(restaurant__pk=1)
Demon Dogs the place
<Place: Demon Dogs the place>
# Add a Waiter to the Restaurant.
>>> w = r.waiter_set.create(name='Joe')
>>> w.save()
>>> w
Joe the waiter at Demon Dogs the restaurant
<Waiter: Joe the waiter at Demon Dogs the restaurant>
# Query the waiters
>>> Waiter.objects.filter(restaurant__place__exact=1)
[Joe the waiter at Demon Dogs the restaurant]
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
>>> Waiter.objects.filter(restaurant__pk=1)
[Joe the waiter at Demon Dogs the restaurant]
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
>>> Waiter.objects.filter(id__exact=1)
[Joe the waiter at Demon Dogs the restaurant]
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
>>> Waiter.objects.filter(pk=1)
[Joe the waiter at Demon Dogs the restaurant]
[<Waiter: Joe the waiter at Demon Dogs the restaurant>]
# Delete the restaurant; the waiter should also be removed
>>> r = Restaurant.objects.get(pk=1)

View File

@ -1,10 +1,10 @@
"""
19. OR lookups
To perform an OR lookup, or a lookup that combines ANDs and ORs,
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
Alternatively, use positional arguments, and pass one or more expressions
of clauses using the variable ``django.db.models.Q`` (or any object with
a get_sql method).
@ -16,10 +16,11 @@ from django.db import models
class Article(models.Model):
headline = models.CharField(maxlength=50)
pub_date = models.DateTimeField()
class Meta:
ordering = ('pub_date',)
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
@ -36,10 +37,10 @@ API_TESTS = """
>>> a3.save()
>>> Article.objects.filter(headline__startswith='Hello') | Article.objects.filter(headline__startswith='Goodbye')
[Hello, Goodbye, Hello and goodbye]
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__startswith='Goodbye'))
[Hello, Goodbye, Hello and goodbye]
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
>>> Article.objects.filter(Q(headline__startswith='Hello') & Q(headline__startswith='Goodbye'))
[]
@ -51,34 +52,34 @@ API_TESTS = """
[]
>>> articles.filter(headline__startswith='Hello') & articles.filter(headline__contains='bye')
[Hello and goodbye]
[<Article: Hello and goodbye>]
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
[Hello and goodbye]
[<Article: Hello and goodbye>]
>>> Article.objects.filter(headline__contains='Hello') | Article.objects.filter(headline__contains='bye')
[Hello, Goodbye, Hello and goodbye]
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
>>> Article.objects.filter(headline__iexact='Hello') | Article.objects.filter(headline__contains='ood')
[Hello, Goodbye, Hello and goodbye]
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
>>> Article.objects.filter(Q(pk=1) | Q(pk=2))
[Hello, Goodbye]
[<Article: Hello>, <Article: Goodbye>]
>>> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))
[Hello, Goodbye, Hello and goodbye]
[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]
# Q arg objects are ANDed
# Q arg objects are ANDed
>>> Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
[Hello and goodbye]
[<Article: Hello and goodbye>]
# Q arg AND order is irrelevant
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
[Hello and goodbye]
[<Article: Hello and goodbye>]
# Try some arg queries with operations other than get_list
>>> Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
Hello and goodbye
<Article: Hello and goodbye>
>>> Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__contains='bye')).count()
3
@ -87,17 +88,17 @@ Hello and goodbye
[{'headline': 'Hello and goodbye', 'pub_date': datetime.datetime(2005, 11, 29, 0, 0), 'id': 3}]
>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2])
{1: Hello}
{1: <Article: Hello>}
# Demonstrating exclude with a Q object
>>> Article.objects.exclude(Q(headline__startswith='Hello'))
[Goodbye]
[<Article: Goodbye>]
# The 'complex_filter' method supports framework features such as
# 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.
>>> Article.objects.complex_filter({'pk': 1})
[Hello]
[<Article: Hello>]
>>> Article.objects.complex_filter(Q(pk=1) | Q(pk=2))
[Hello, Goodbye]
[<Article: Hello>, <Article: Goodbye>]
"""

View File

@ -21,7 +21,7 @@ class Article(models.Model):
class Meta:
ordering = ('-pub_date', 'headline')
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
@ -39,26 +39,26 @@ API_TESTS = """
# By default, Article.objects.all() orders by pub_date descending, then
# headline ascending.
>>> Article.objects.all()
[Article 4, Article 2, Article 3, Article 1]
[<Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
# Override ordering with order_by, which is in the same format as the ordering
# attribute in models.
>>> Article.objects.order_by('headline')
[Article 1, Article 2, Article 3, Article 4]
[<Article: Article 1>, <Article: Article 2>, <Article: Article 3>, <Article: Article 4>]
>>> Article.objects.order_by('pub_date', '-headline')
[Article 1, Article 3, Article 2, Article 4]
[<Article: Article 1>, <Article: Article 3>, <Article: Article 2>, <Article: Article 4>]
# Use the 'stop' part of slicing notation to limit the results.
>>> Article.objects.order_by('headline')[:2]
[Article 1, Article 2]
[<Article: Article 1>, <Article: Article 2>]
# Use the 'stop' and 'start' parts of slicing notation to offset the result list.
>>> Article.objects.order_by('headline')[1:3]
[Article 2, Article 3]
[<Article: Article 2>, <Article: Article 3>]
# Getting a single item should work too:
>>> Article.objects.all()[0]
Article 4
<Article: Article 4>
# Use '?' to order randomly. (We're using [...] in the output to indicate we
# don't know what order the output will be in.

View File

@ -12,7 +12,7 @@ class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline')
pub_date = models.DateTimeField()
def __repr__(self):
def __str__(self):
return self.headline
API_TESTS = """
@ -35,11 +35,11 @@ API_TESTS = """
# get the first page (zero-based)
>>> paginator.get_page(0)
[Article 1, Article 2, Article 3, Article 4, Article 5]
[<Article: Article 1>, <Article: Article 2>, <Article: Article 3>, <Article: Article 4>, <Article: Article 5>]
# get the second page
>>> paginator.get_page(1)
[Article 6, Article 7, Article 8, Article 9]
[<Article: Article 6>, <Article: Article 7>, <Article: Article 8>, <Article: Article 9>]
# does the first page have a next or previous page?
>>> paginator.has_next_page(0)

View File

@ -21,7 +21,7 @@ class Thing(models.Model):
class Meta:
db_table = 'select'
def __repr__(self):
def __str__(self):
return self.when
API_TESTS = """
@ -39,18 +39,18 @@ a
h
>>> Thing.objects.order_by('when')
[a, h]
[<Thing: a>, <Thing: h>]
>>> v = Thing.objects.get(pk='a')
>>> print v.join
b
>>> print v.where
2005-01-01
>>> Thing.objects.order_by('select.when')
[a, h]
[<Thing: a>, <Thing: h>]
>>> Thing.objects.dates('where', 'year')
[datetime.datetime(2005, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)]
>>> Thing.objects.filter(where__month=1)
[a]
[<Thing: a>]
"""

View File

@ -8,20 +8,23 @@ from django.db import models
class User(models.Model):
name = models.CharField(maxlength=200)
def __repr__(self):
def __str__(self):
return self.name
class Poll(models.Model):
question = models.CharField(maxlength=200)
creator = models.ForeignKey(User)
def __repr__(self):
def __str__(self):
return self.question
class Choice(models.Model):
name = models.CharField(maxlength=100)
poll = models.ForeignKey(Poll, related_name="poll_choice")
related_poll = models.ForeignKey(Poll, related_name="related_choice")
def __repr(self):
def __str(self):
return self.name
API_TESTS = """
@ -38,15 +41,15 @@ API_TESTS = """
>>> # Reverse lookups by field name:
>>> User.objects.get(poll__question__exact="What's the first question?")
John Doe
<User: John Doe>
>>> User.objects.get(poll__question__exact="What's the second question?")
Jim Bo
<User: Jim Bo>
>>> # Reverse lookups by related_name:
>>> Poll.objects.get(poll_choice__name__exact="This is the answer.")
What's the first question?
<Poll: What's the first question?>
>>> Poll.objects.get(related_choice__name__exact="This is the answer.")
What's the second question?
<Poll: What's the second question?>
>>> # If a related_name is given you can't use the field name instead:
>>> Poll.objects.get(choice__name__exact="This is the answer")

View File

@ -11,7 +11,7 @@ class Person(models.Model):
first_name = models.CharField(maxlength=20)
last_name = models.CharField(maxlength=20)
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
def save(self):
@ -31,7 +31,7 @@ Before save
After save
>>> Person.objects.all()
[John Smith]
[<Person: John Smith>]
>>> p1.delete()
Before deletion

View File

@ -14,7 +14,7 @@ class Reporter(models.Model):
last_name = models.CharField(maxlength=30)
email = models.EmailField()
def __repr__(self):
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
API_TESTS = """
@ -40,7 +40,7 @@ Exception: I meant to do that
# The object created before the exception still exists
>>> Reporter.objects.all()
[Alice Smith]
[<Reporter: Alice Smith>]
# the autocommit decorator works exactly the same as the default behavior
>>> autocomitted_create_then_fail = transaction.autocommit(create_a_reporter_then_fail)
@ -51,7 +51,7 @@ Exception: I meant to do that
# Same behavior as before
>>> Reporter.objects.all()
[Alice Smith, Ben Jones]
[<Reporter: Alice Smith>, <Reporter: Ben Jones>]
# With the commit_on_success decorator, the transaction is only comitted if the
# function doesn't throw an exception
@ -63,7 +63,7 @@ Exception: I meant to do that
# This time the object never got saved
>>> Reporter.objects.all()
[Alice Smith, Ben Jones]
[<Reporter: Alice Smith>, <Reporter: Ben Jones>]
# If there aren't any exceptions, the data will get saved
>>> def remove_a_reporter():
@ -73,7 +73,7 @@ Exception: I meant to do that
>>> remove_comitted_on_success = transaction.commit_on_success(remove_a_reporter)
>>> remove_comitted_on_success()
>>> Reporter.objects.all()
[Ben Jones]
[<Reporter: Ben Jones>]
# You can manually manage transactions if you really want to, but you
# have to remember to commit/rollback
@ -84,7 +84,7 @@ Exception: I meant to do that
>>> manually_managed = transaction.commit_manually(manually_managed)
>>> manually_managed()
>>> Reporter.objects.all()
[Ben Jones, Carol Doe]
[<Reporter: Ben Jones>, <Reporter: Carol Doe>]
# If you forget, you'll get bad errors
>>> def manually_managed_mistake():

View File

@ -17,7 +17,7 @@ class Person(models.Model):
favorite_moment = models.DateTimeField()
email = models.EmailField()
def __repr__(self):
def __str__(self):
return self.name
API_TESTS = """