diff options
-rw-r--r-- | docs/changelog.rst | 11 | ||||
-rw-r--r-- | docs/orms.rst | 15 | ||||
-rw-r--r-- | factory/base.py | 2 | ||||
-rw-r--r-- | tests/djapp/models.py | 11 | ||||
-rw-r--r-- | tests/test_django.py | 21 |
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): |