summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël Barrois <raphael.barrois@polytechnique.org>2015-05-31 10:47:28 +0100
committerRaphaël Barrois <raphael.barrois@polytechnique.org>2015-05-31 10:47:28 +0100
commit0b5270eab393fad20faa7a6a9720af18c97b1773 (patch)
treede32d3300256be1bfc8626361970efa32b133ce5
parente9851a7d51afffea2a5679934ad6284c0835cfa2 (diff)
downloadfactory-boy-0b5270eab393fad20faa7a6a9720af18c97b1773.tar
factory-boy-0b5270eab393fad20faa7a6a9720af18c97b1773.tar.gz
Properly handle custom Django managers (Closes #201).
The actual behavior of Django with custom managers and inherited abstract models is rather complex, so this had to be adapted to the actual Django source code.
-rw-r--r--docs/changelog.rst4
-rw-r--r--factory/django.py9
-rw-r--r--tests/djapp/models.py11
-rw-r--r--tests/test_django.py13
4 files changed, 35 insertions, 2 deletions
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 0cbd4af..c871ce8 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -15,6 +15,10 @@ ChangeLog
thus allowing to pass in a lazy iterator such as a Django queryset
(i.e ``factory.Iterator(models.MyThingy.objects.all())``).
+*Bugfix:*
+
+ - :issue:`201`: Properly handle custom Django managers when dealing with abstract Django models.
+
.. _v2.5.2:
2.5.2 (2015-04-21)
diff --git a/factory/django.py b/factory/django.py
index 74e4fdb..e4a3ea7 100644
--- a/factory/django.py
+++ b/factory/django.py
@@ -115,7 +115,14 @@ class DjangoModelFactory(base.Factory):
if model_class is None:
raise base.AssociatedClassError("No model set on %s.%s.Meta"
% (cls.__module__, cls.__name__))
- manager = model_class.objects
+
+ try:
+ manager = model_class.objects
+ except AttributeError:
+ # When inheriting from an abstract model with a custom
+ # manager, the class has no 'objects' field.
+ manager = model_class._default_manager
+
if cls._meta.database != DEFAULT_DB_ALIAS:
manager = manager.using(cls._meta.database)
return manager
diff --git a/tests/djapp/models.py b/tests/djapp/models.py
index 68b9709..cadefbc 100644
--- a/tests/djapp/models.py
+++ b/tests/djapp/models.py
@@ -110,3 +110,14 @@ class WithCustomManager(models.Model):
foo = models.CharField(max_length=20)
objects = CustomManager()
+
+
+class AbstractWithCustomManager(models.Model):
+ custom_objects = CustomManager()
+
+ class Meta:
+ abstract = True
+
+
+class FromAbstractWithCustomManager(AbstractWithCustomManager):
+ pass
diff --git a/tests/test_django.py b/tests/test_django.py
index bde8efe..b8e7ccb 100644
--- a/tests/test_django.py
+++ b/tests/test_django.py
@@ -755,10 +755,21 @@ class PreventSignalsTestCase(unittest.TestCase):
self.assertSignalsReactivated()
-class DjangoCustomManagerTestCase(django_test.TestCase):
+@unittest.skipIf(django is None, "Django not installed.")
+class DjangoCustomManagerTestCase(unittest.TestCase):
def test_extra_args(self):
+ # Our CustomManager will remove the 'arg=' argument.
model = WithCustomManagerFactory(arg='foo')
+ def test_with_manager_on_abstract(self):
+ class ObjFactory(factory.django.DjangoModelFactory):
+ class Meta:
+ model = models.FromAbstractWithCustomManager
+
+ # Our CustomManager will remove the 'arg=' argument,
+ # invalid for the actual model.
+ ObjFactory.create(arg='invalid')
+
if __name__ == '__main__': # pragma: no cover
unittest.main()