aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël Barrois <raphael.barrois@polytechnique.org>2013-09-25 10:58:12 +0200
committerRaphaël Barrois <raphael.barrois@polytechnique.org>2013-09-25 10:58:12 +0200
commit2e5046bda818771f474a1514465f71bd62be9dcd (patch)
treeade9d0c6f02fbc4dfbe066b41c6765c215a68f81
parentea00fa30273c7355c02a361c1193ea4764528edb (diff)
downloadfactory-boy-2e5046bda818771f474a1514465f71bd62be9dcd.tar
factory-boy-2e5046bda818771f474a1514465f71bd62be9dcd.tar.gz
Fix Django sequences with abstract base models.
-rw-r--r--docs/changelog.rst11
-rw-r--r--docs/orms.rst15
-rw-r--r--factory/base.py2
-rw-r--r--tests/djapp/models.py11
-rw-r--r--tests/test_django.py21
5 files changed, 59 insertions, 1 deletions
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 3e07a82..e5fe303 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,6 +1,17 @@
ChangeLog
=========
+
+.. _v2.2.1:
+
+2.2.1 (2013-09-24)
+------------------
+
+*Bugfix:*
+
+ - Fixed sequence counter for :class:`~factory.django.DjangoModelFactory` when a factory
+ inherits from another factory relating to an abstract model.
+
.. _v2.2.0:
2.2.0 (2013-09-24)
diff --git a/docs/orms.rst b/docs/orms.rst
index a463bfb..33b3e0a 100644
--- a/docs/orms.rst
+++ b/docs/orms.rst
@@ -74,6 +74,21 @@ All factories for a Django :class:`~django.db.models.Model` should use the
[<User: john>, <User: jack>]
+.. note:: If a :class:`DjangoModelFactory` relates to an :obj:`~django.db.models.Options.abstract`
+ model, be sure to declare the :class:`DjangoModelFactory` as abstract:
+
+ .. code-block:: python
+
+ class MyAbstractModelFactory(factory.django.DjangoModelFactory):
+ FACTORY_FOR = models.MyAbstractModel
+ ABSTRACT_FACTORY = True
+
+ class MyConcreteModelFactory(MyAbstractModel):
+ FACTORY_FOR = models.MyConcreteModel
+
+ Otherwise, factory_boy will try to get the 'next PK' counter from the abstract model.
+
+
.. class:: FileField
Custom declarations for :class:`django.db.models.FileField`
diff --git a/factory/base.py b/factory/base.py
index 462a60c..8183649 100644
--- a/factory/base.py
+++ b/factory/base.py
@@ -328,7 +328,7 @@ class BaseFactory(object):
"""
# Rely upon our parents
- if cls._base_factory:
+ if cls._base_factory and not cls._base_factory._abstract_factory:
logger.debug("%r: reusing sequence from %r", cls, cls._base_factory)
return cls._base_factory._generate_next_sequence()
diff --git a/tests/djapp/models.py b/tests/djapp/models.py
index cc34643..3f25fbb 100644
--- a/tests/djapp/models.py
+++ b/tests/djapp/models.py
@@ -44,6 +44,17 @@ class NonIntegerPk(models.Model):
bar = models.CharField(max_length=20, blank=True)
+class AbstractBase(models.Model):
+ foo = models.CharField(max_length=20)
+
+ class Meta:
+ abstract = True
+
+
+class ConcreteSon(AbstractBase):
+ pass
+
+
WITHFILE_UPLOAD_TO = 'django'
WITHFILE_UPLOAD_DIR = os.path.join(settings.MEDIA_ROOT, WITHFILE_UPLOAD_TO)
diff --git a/tests/test_django.py b/tests/test_django.py
index b27562c..7cebf8d 100644
--- a/tests/test_django.py
+++ b/tests/test_django.py
@@ -64,6 +64,8 @@ else: # pragma: no cover
models = Fake()
models.StandardModel = Fake
+ models.AbstractBase = Fake
+ models.ConcreteSon = Fake
models.NonIntegerPk = Fake
models.WithFile = Fake
models.WithImage = Fake
@@ -106,6 +108,17 @@ class NonIntegerPkFactory(factory.django.DjangoModelFactory):
bar = ''
+class AbstractBaseFactory(factory.django.DjangoModelFactory):
+ FACTORY_FOR = models.AbstractBase
+ ABSTRACT_FACTORY = True
+
+ foo = factory.Sequence(lambda n: "foo%d" % n)
+
+
+class ConcreteSonFactory(AbstractBaseFactory):
+ FACTORY_FOR = models.ConcreteSon
+
+
class WithFileFactory(factory.django.DjangoModelFactory):
FACTORY_FOR = models.WithFile
@@ -224,6 +237,14 @@ class DjangoNonIntegerPkTestCase(django_test.TestCase):
@unittest.skipIf(django is None, "Django not installed.")
+class DjangoAbstractBaseSequenceTestCase(django_test.TestCase):
+ def test_auto_sequence(self):
+ with factory.debug():
+ obj = ConcreteSonFactory()
+ self.assertEqual(1, obj.pk)
+
+
+@unittest.skipIf(django is None, "Django not installed.")
class DjangoFileFieldTestCase(unittest.TestCase):
def tearDown(self):