Consolidated some many_to_one tests.
This commit is contained in:
parent
2a1bdf5ced
commit
1fd6e13bf2
|
@ -30,3 +30,71 @@ class Article(models.Model):
|
|||
|
||||
class Meta:
|
||||
ordering = ('headline',)
|
||||
|
||||
|
||||
# If ticket #1578 ever slips back in, these models will not be able to be
|
||||
# created (the field names being lower-cased versions of their opposite
|
||||
# classes is important here).
|
||||
class First(models.Model):
|
||||
second = models.IntegerField()
|
||||
|
||||
|
||||
class Second(models.Model):
|
||||
first = models.ForeignKey(First, related_name='the_first')
|
||||
|
||||
|
||||
# Protect against repetition of #1839, #2415 and #2536.
|
||||
class Third(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
third = models.ForeignKey('self', null=True, related_name='child_set')
|
||||
|
||||
|
||||
class Parent(models.Model):
|
||||
name = models.CharField(max_length=20, unique=True)
|
||||
bestchild = models.ForeignKey('Child', null=True, related_name='favored_by')
|
||||
|
||||
|
||||
class Child(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
parent = models.ForeignKey(Parent)
|
||||
|
||||
|
||||
class ToFieldChild(models.Model):
|
||||
parent = models.ForeignKey(Parent, to_field='name')
|
||||
|
||||
|
||||
# Multiple paths to the same model (#7110, #7125)
|
||||
@python_2_unicode_compatible
|
||||
class Category(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Record(models.Model):
|
||||
category = models.ForeignKey(Category)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Relation(models.Model):
|
||||
left = models.ForeignKey(Record, related_name='left_set')
|
||||
right = models.ForeignKey(Record, related_name='right_set')
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s" % (self.left.category.name, self.right.category.name)
|
||||
|
||||
|
||||
# Test related objects visibility.
|
||||
class SchoolManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return super(SchoolManager, self).get_queryset().filter(is_public=True)
|
||||
|
||||
|
||||
class School(models.Model):
|
||||
is_public = models.BooleanField(default=False)
|
||||
objects = SchoolManager()
|
||||
|
||||
|
||||
class Student(models.Model):
|
||||
school = models.ForeignKey(School)
|
||||
|
|
|
@ -2,12 +2,13 @@ from copy import deepcopy
|
|||
import datetime
|
||||
|
||||
from django.core.exceptions import MultipleObjectsReturned, FieldError
|
||||
from django.db import transaction
|
||||
from django.db import models, transaction
|
||||
from django.test import TestCase
|
||||
from django.utils import six
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from .models import Article, Reporter
|
||||
from .models import (Article, Reporter, First, Third, Parent, Child,
|
||||
ToFieldChild, Category, Record, Relation, School, Student)
|
||||
|
||||
|
||||
class ManyToOneTests(TestCase):
|
||||
|
@ -374,12 +375,6 @@ class ManyToOneTests(TestCase):
|
|||
self.assertQuerysetEqual(Reporter.objects.all(), [])
|
||||
self.assertQuerysetEqual(Article.objects.all(), [])
|
||||
|
||||
def test_regression_12876(self):
|
||||
# Regression for #12876 -- Model methods that include queries that
|
||||
# recursive don't cause recursion depth problems under deepcopy.
|
||||
self.r.cached_query = Article.objects.filter(reporter=self.r)
|
||||
self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
|
||||
|
||||
def test_explicit_fk(self):
|
||||
# Create a new Article with get_or_create using an explicit value
|
||||
# for a ForeignKey.
|
||||
|
@ -411,6 +406,12 @@ class ManyToOneTests(TestCase):
|
|||
repr(Article.objects.get(reporter_id=self.r2.id,
|
||||
pub_date=datetime.date(2011, 5, 7))))
|
||||
|
||||
def test_deepcopy_and_circular_references(self):
|
||||
# Regression for #12876 -- Model methods that include queries that
|
||||
# recursive don't cause recursion depth problems under deepcopy.
|
||||
self.r.cached_query = Article.objects.filter(reporter=self.r)
|
||||
self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")
|
||||
|
||||
def test_manager_class_caching(self):
|
||||
r1 = Reporter.objects.create(first_name='Mike')
|
||||
r2 = Reporter.objects.create(first_name='John')
|
||||
|
@ -443,3 +444,154 @@ class ManyToOneTests(TestCase):
|
|||
expected_message % ', '.join(['EXTRA'] + Article._meta.get_all_field_names()),
|
||||
Article.objects.extra(select={'EXTRA': 'EXTRA_SELECT'}).values_list,
|
||||
'notafield')
|
||||
|
||||
def test_fk_assignment_and_related_object_cache(self):
|
||||
# Tests of ForeignKey assignment and the related-object cache (see #6886).
|
||||
|
||||
p = Parent.objects.create(name="Parent")
|
||||
c = Child.objects.create(name="Child", parent=p)
|
||||
|
||||
# Look up the object again so that we get a "fresh" object.
|
||||
c = Child.objects.get(name="Child")
|
||||
p = c.parent
|
||||
|
||||
# Accessing the related object again returns the exactly same object.
|
||||
self.assertTrue(c.parent is p)
|
||||
|
||||
# But if we kill the cache, we get a new object.
|
||||
del c._parent_cache
|
||||
self.assertFalse(c.parent is p)
|
||||
|
||||
# Assigning a new object results in that object getting cached immediately.
|
||||
p2 = Parent.objects.create(name="Parent 2")
|
||||
c.parent = p2
|
||||
self.assertTrue(c.parent is p2)
|
||||
|
||||
# Assigning None succeeds if field is null=True.
|
||||
p.bestchild = None
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# bestchild should still be None after saving.
|
||||
p.save()
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# bestchild should still be None after fetching the object again.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# Assigning None fails: Child.parent is null=False.
|
||||
self.assertRaises(ValueError, setattr, c, "parent", None)
|
||||
|
||||
# You also can't assign an object of the wrong type here
|
||||
self.assertRaises(ValueError, setattr, c, "parent", First(id=1, second=1))
|
||||
|
||||
# Nor can you explicitly assign None to Child.parent during object
|
||||
# creation (regression for #9649).
|
||||
self.assertRaises(ValueError, Child, name='xyzzy', parent=None)
|
||||
self.assertRaises(ValueError, Child.objects.create, name='xyzzy', parent=None)
|
||||
|
||||
# Creation using keyword argument should cache the related object.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
c = Child(parent=p)
|
||||
self.assertTrue(c.parent is p)
|
||||
|
||||
# Creation using keyword argument and unsaved related instance (#8070).
|
||||
p = Parent()
|
||||
with self.assertRaisesMessage(ValueError,
|
||||
'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
|
||||
% (p, Child.parent.field.rel.to._meta.object_name)):
|
||||
Child(parent=p)
|
||||
|
||||
with self.assertRaisesMessage(ValueError,
|
||||
'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
|
||||
% (p, Child.parent.field.rel.to._meta.object_name)):
|
||||
ToFieldChild(parent=p)
|
||||
|
||||
# Creation using attname keyword argument and an id will cause the
|
||||
# related object to be fetched.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
c = Child(parent_id=p.id)
|
||||
self.assertFalse(c.parent is p)
|
||||
self.assertEqual(c.parent, p)
|
||||
|
||||
def test_multiple_foreignkeys(self):
|
||||
# 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)
|
||||
Relation.objects.create(left=r1, right=r2)
|
||||
Relation.objects.create(left=r3, right=r4)
|
||||
Relation.objects.create(left=r1, right=r3)
|
||||
Relation.objects.create(left=r5, right=r2)
|
||||
Relation.objects.create(left=r3, right=r2)
|
||||
|
||||
q1 = Relation.objects.filter(left__category__name__in=['First'], right__category__name__in=['Second'])
|
||||
self.assertQuerysetEqual(q1, ["<Relation: First - Second>"])
|
||||
|
||||
q2 = Category.objects.filter(record__left_set__right__category__name='Second').order_by('name')
|
||||
self.assertQuerysetEqual(q2, ["<Category: First>", "<Category: Second>"])
|
||||
|
||||
p = Parent.objects.create(name="Parent")
|
||||
c = Child.objects.create(name="Child", parent=p)
|
||||
self.assertRaises(ValueError, Child.objects.create, name="Grandchild", parent=c)
|
||||
|
||||
def test_fk_instantiation_outside_model(self):
|
||||
# Regression for #12190 -- Should be able to instantiate a FK outside
|
||||
# of a model, and interrogate its related field.
|
||||
cat = models.ForeignKey(Category)
|
||||
self.assertEqual('id', cat.rel.get_related_field().name)
|
||||
|
||||
def test_relation_unsaved(self):
|
||||
# Test that the <field>_set manager does not join on Null value fields (#17541)
|
||||
Third.objects.create(name='Third 1')
|
||||
Third.objects.create(name='Third 2')
|
||||
th = Third(name="testing")
|
||||
# The object isn't saved an thus the relation field is null - we won't even
|
||||
# execute a query in this case.
|
||||
with self.assertNumQueries(0):
|
||||
self.assertEqual(th.child_set.count(), 0)
|
||||
th.save()
|
||||
# Now the model is saved, so we will need to execute an query.
|
||||
with self.assertNumQueries(1):
|
||||
self.assertEqual(th.child_set.count(), 0)
|
||||
|
||||
def test_related_object(self):
|
||||
public_school = School.objects.create(is_public=True)
|
||||
public_student = Student.objects.create(school=public_school)
|
||||
|
||||
private_school = School.objects.create(is_public=False)
|
||||
private_student = Student.objects.create(school=private_school)
|
||||
|
||||
# Only one school is available via all() due to the custom default manager.
|
||||
self.assertQuerysetEqual(
|
||||
School.objects.all(),
|
||||
["<School: School object>"]
|
||||
)
|
||||
|
||||
self.assertEqual(public_student.school, public_school)
|
||||
|
||||
# Make sure the base manager is used so that an student can still access
|
||||
# its related school even if the default manager doesn't normally
|
||||
# allow it.
|
||||
self.assertEqual(private_student.school, private_school)
|
||||
|
||||
# If the manager is marked "use_for_related_fields", it'll get used instead
|
||||
# of the "bare" queryset. Usually you'd define this as a property on the class,
|
||||
# but this approximates that in a way that's easier in tests.
|
||||
School.objects.use_for_related_fields = True
|
||||
try:
|
||||
private_student = Student.objects.get(pk=private_student.pk)
|
||||
self.assertRaises(School.DoesNotExist, lambda: private_student.school)
|
||||
finally:
|
||||
School.objects.use_for_related_fields = False
|
||||
|
||||
def test_hasattr_related_object(self):
|
||||
# The exception raised on attribute access when a related object
|
||||
# doesn't exist should be an instance of a subclass of `AttributeError`
|
||||
# refs #21563
|
||||
self.assertFalse(hasattr(Article(), 'reporter'))
|
||||
|
|
|
@ -27,3 +27,11 @@ class Article(models.Model):
|
|||
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
|
||||
class Car(models.Model):
|
||||
make = models.CharField(max_length=100, null=True, unique=True)
|
||||
|
||||
|
||||
class Driver(models.Model):
|
||||
car = models.ForeignKey(Car, to_field='make', null=True, related_name='drivers')
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||
|
||||
from django.test import TestCase
|
||||
|
||||
from .models import Reporter, Article
|
||||
from .models import Article, Car, Driver, Reporter
|
||||
|
||||
|
||||
class ManyToOneNullTests(TestCase):
|
||||
|
@ -105,3 +105,10 @@ class ManyToOneNullTests(TestCase):
|
|||
with self.assertNumQueries(1):
|
||||
r.article_set.clear()
|
||||
self.assertEqual(r.article_set.count(), 0)
|
||||
|
||||
def test_related_null_to_field(self):
|
||||
c1 = Car.objects.create()
|
||||
d1 = Driver.objects.create()
|
||||
self.assertIs(d1.car, None)
|
||||
with self.assertNumQueries(0):
|
||||
self.assertEqual(list(c1.drivers.all()), [])
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
"""
|
||||
Regression tests for a few ForeignKey bugs.
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
# If ticket #1578 ever slips back in, these models will not be able to be
|
||||
# created (the field names being lower-cased versions of their opposite
|
||||
# classes is important here).
|
||||
|
||||
|
||||
class First(models.Model):
|
||||
second = models.IntegerField()
|
||||
|
||||
|
||||
class Second(models.Model):
|
||||
first = models.ForeignKey(First, related_name='the_first')
|
||||
|
||||
|
||||
# Protect against repetition of #1839, #2415 and #2536.
|
||||
class Third(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
third = models.ForeignKey('self', null=True, related_name='child_set')
|
||||
|
||||
|
||||
class Parent(models.Model):
|
||||
name = models.CharField(max_length=20, unique=True)
|
||||
bestchild = models.ForeignKey('Child', null=True, related_name='favored_by')
|
||||
|
||||
|
||||
class Child(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
parent = models.ForeignKey(Parent)
|
||||
|
||||
|
||||
class ToFieldChild(models.Model):
|
||||
parent = models.ForeignKey(Parent, to_field='name')
|
||||
|
||||
|
||||
# Multiple paths to the same model (#7110, #7125)
|
||||
@python_2_unicode_compatible
|
||||
class Category(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Record(models.Model):
|
||||
category = models.ForeignKey(Category)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Relation(models.Model):
|
||||
left = models.ForeignKey(Record, related_name='left_set')
|
||||
right = models.ForeignKey(Record, related_name='right_set')
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s" % (self.left.category.name, self.right.category.name)
|
||||
|
||||
|
||||
class Car(models.Model):
|
||||
make = models.CharField(max_length=100, null=True, unique=True)
|
||||
|
||||
|
||||
class Driver(models.Model):
|
||||
car = models.ForeignKey(Car, to_field='make', null=True, related_name='drivers')
|
|
@ -1,137 +0,0 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
|
||||
from .models import (
|
||||
First, Third, Parent, Child, ToFieldChild, Category, Record, Relation, Car, Driver)
|
||||
|
||||
|
||||
class ManyToOneRegressionTests(TestCase):
|
||||
def test_object_creation(self):
|
||||
Third.objects.create(id='3', name='An example')
|
||||
parent = Parent(name='fred')
|
||||
parent.save()
|
||||
Child.objects.create(name='bam-bam', parent=parent)
|
||||
|
||||
def test_fk_assignment_and_related_object_cache(self):
|
||||
# Tests of ForeignKey assignment and the related-object cache (see #6886).
|
||||
|
||||
p = Parent.objects.create(name="Parent")
|
||||
c = Child.objects.create(name="Child", parent=p)
|
||||
|
||||
# Look up the object again so that we get a "fresh" object.
|
||||
c = Child.objects.get(name="Child")
|
||||
p = c.parent
|
||||
|
||||
# Accessing the related object again returns the exactly same object.
|
||||
self.assertTrue(c.parent is p)
|
||||
|
||||
# But if we kill the cache, we get a new object.
|
||||
del c._parent_cache
|
||||
self.assertFalse(c.parent is p)
|
||||
|
||||
# Assigning a new object results in that object getting cached immediately.
|
||||
p2 = Parent.objects.create(name="Parent 2")
|
||||
c.parent = p2
|
||||
self.assertTrue(c.parent is p2)
|
||||
|
||||
# Assigning None succeeds if field is null=True.
|
||||
p.bestchild = None
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# bestchild should still be None after saving.
|
||||
p.save()
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# bestchild should still be None after fetching the object again.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
self.assertTrue(p.bestchild is None)
|
||||
|
||||
# Assigning None fails: Child.parent is null=False.
|
||||
self.assertRaises(ValueError, setattr, c, "parent", None)
|
||||
|
||||
# You also can't assign an object of the wrong type here
|
||||
self.assertRaises(ValueError, setattr, c, "parent", First(id=1, second=1))
|
||||
|
||||
# Nor can you explicitly assign None to Child.parent during object
|
||||
# creation (regression for #9649).
|
||||
self.assertRaises(ValueError, Child, name='xyzzy', parent=None)
|
||||
self.assertRaises(ValueError, Child.objects.create, name='xyzzy', parent=None)
|
||||
|
||||
# Creation using keyword argument should cache the related object.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
c = Child(parent=p)
|
||||
self.assertTrue(c.parent is p)
|
||||
|
||||
# Creation using keyword argument and unsaved related instance (#8070).
|
||||
p = Parent()
|
||||
with self.assertRaisesMessage(ValueError,
|
||||
'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
|
||||
% (p, Child.parent.field.rel.to._meta.object_name)):
|
||||
Child(parent=p)
|
||||
|
||||
with self.assertRaisesMessage(ValueError,
|
||||
'Cannot assign "%r": "%s" instance isn\'t saved in the database.'
|
||||
% (p, Child.parent.field.rel.to._meta.object_name)):
|
||||
ToFieldChild(parent=p)
|
||||
|
||||
# Creation using attname keyword argument and an id will cause the
|
||||
# related object to be fetched.
|
||||
p = Parent.objects.get(name="Parent")
|
||||
c = Child(parent_id=p.id)
|
||||
self.assertFalse(c.parent is p)
|
||||
self.assertEqual(c.parent, p)
|
||||
|
||||
def test_multiple_foreignkeys(self):
|
||||
# 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)
|
||||
Relation.objects.create(left=r1, right=r2)
|
||||
Relation.objects.create(left=r3, right=r4)
|
||||
Relation.objects.create(left=r1, right=r3)
|
||||
Relation.objects.create(left=r5, right=r2)
|
||||
Relation.objects.create(left=r3, right=r2)
|
||||
|
||||
q1 = Relation.objects.filter(left__category__name__in=['First'], right__category__name__in=['Second'])
|
||||
self.assertQuerysetEqual(q1, ["<Relation: First - Second>"])
|
||||
|
||||
q2 = Category.objects.filter(record__left_set__right__category__name='Second').order_by('name')
|
||||
self.assertQuerysetEqual(q2, ["<Category: First>", "<Category: Second>"])
|
||||
|
||||
p = Parent.objects.create(name="Parent")
|
||||
c = Child.objects.create(name="Child", parent=p)
|
||||
self.assertRaises(ValueError, Child.objects.create, name="Grandchild", parent=c)
|
||||
|
||||
def test_fk_instantiation_outside_model(self):
|
||||
# Regression for #12190 -- Should be able to instantiate a FK outside
|
||||
# of a model, and interrogate its related field.
|
||||
cat = models.ForeignKey(Category)
|
||||
self.assertEqual('id', cat.rel.get_related_field().name)
|
||||
|
||||
def test_relation_unsaved(self):
|
||||
# Test that the <field>_set manager does not join on Null value fields (#17541)
|
||||
Third.objects.create(name='Third 1')
|
||||
Third.objects.create(name='Third 2')
|
||||
th = Third(name="testing")
|
||||
# The object isn't saved an thus the relation field is null - we won't even
|
||||
# execute a query in this case.
|
||||
with self.assertNumQueries(0):
|
||||
self.assertEqual(th.child_set.count(), 0)
|
||||
th.save()
|
||||
# Now the model is saved, so we will need to execute an query.
|
||||
with self.assertNumQueries(1):
|
||||
self.assertEqual(th.child_set.count(), 0)
|
||||
|
||||
def test_related_null_to_field(self):
|
||||
c1 = Car.objects.create()
|
||||
d1 = Driver.objects.create()
|
||||
self.assertIs(d1.car, None)
|
||||
with self.assertNumQueries(0):
|
||||
self.assertEqual(list(c1.drivers.all()), [])
|
|
@ -1,15 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class SourceManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return super(SourceManager, self).get_queryset().filter(is_public=True)
|
||||
|
||||
|
||||
class Source(models.Model):
|
||||
is_public = models.BooleanField(default=False)
|
||||
objects = SourceManager()
|
||||
|
||||
|
||||
class Item(models.Model):
|
||||
source = models.ForeignKey(Source)
|
|
@ -1,46 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from .models import Source, Item
|
||||
|
||||
|
||||
class ReverseSingleRelatedTests(TestCase):
|
||||
"""
|
||||
Regression tests for an object that cannot access a single related
|
||||
object due to a restrictive default manager.
|
||||
"""
|
||||
|
||||
def test_reverse_single_related(self):
|
||||
|
||||
public_source = Source.objects.create(is_public=True)
|
||||
public_item = Item.objects.create(source=public_source)
|
||||
|
||||
private_source = Source.objects.create(is_public=False)
|
||||
private_item = Item.objects.create(source=private_source)
|
||||
|
||||
# Only one source is available via all() due to the custom default manager.
|
||||
self.assertQuerysetEqual(
|
||||
Source.objects.all(),
|
||||
["<Source: Source object>"]
|
||||
)
|
||||
|
||||
self.assertEqual(public_item.source, public_source)
|
||||
|
||||
# Make sure that an item can still access its related source even if the default
|
||||
# manager doesn't normally allow it.
|
||||
self.assertEqual(private_item.source, private_source)
|
||||
|
||||
# If the manager is marked "use_for_related_fields", it'll get used instead
|
||||
# of the "bare" queryset. Usually you'd define this as a property on the class,
|
||||
# but this approximates that in a way that's easier in tests.
|
||||
Source.objects.use_for_related_fields = True
|
||||
try:
|
||||
private_item = Item.objects.get(pk=private_item.pk)
|
||||
self.assertRaises(Source.DoesNotExist, lambda: private_item.source)
|
||||
finally:
|
||||
Source.objects.use_for_related_fields = False
|
||||
|
||||
def test_hasattr_single_related(self):
|
||||
# The exception raised on attribute access when a related object
|
||||
# doesn't exist should be an instance of a subclass of `AttributeError`
|
||||
# refs #21563
|
||||
self.assertFalse(hasattr(Item(), 'source'))
|
Loading…
Reference in New Issue