diff options
Diffstat (limited to 'docs/orms.rst')
-rw-r--r-- | docs/orms.rst | 212 |
1 files changed, 207 insertions, 5 deletions
diff --git a/docs/orms.rst b/docs/orms.rst index 8e5b6f6..e50e706 100644 --- a/docs/orms.rst +++ b/docs/orms.rst @@ -11,6 +11,8 @@ adding dedicated features. Django ------ +.. currentmodule:: factory.django + The first versions of factory_boy were designed specifically for Django, but the library has now evolved to be framework-independant. @@ -24,14 +26,16 @@ All factories for a Django :class:`~django.db.models.Model` should use the :class:`DjangoModelFactory` base class. -.. class:: DjangoModelFactory(Factory) +.. class:: DjangoModelFactory(factory.Factory) Dedicated class for Django :class:`~django.db.models.Model` factories. This class provides the following features: - * :func:`~Factory.create()` uses :meth:`Model.objects.create() <django.db.models.query.QuerySet.create>` - * :func:`~Factory._setup_next_sequence()` selects the next unused primary key value + * The :attr:`~factory.Factory.FACTORY_FOR` attribute also supports the ``'app.Model'`` + syntax + * :func:`~factory.Factory.create()` uses :meth:`Model.objects.create() <django.db.models.query.QuerySet.create>` + * :func:`~factory.Factory._setup_next_sequence()` selects the next unused primary key value * When using :class:`~factory.RelatedFactory` or :class:`~factory.PostGeneration` attributes, the base object will be :meth:`saved <django.db.models.Model.save>` once all post-generation hooks have run. @@ -44,8 +48,8 @@ All factories for a Django :class:`~django.db.models.Model` should use the .. code-block:: python - class UserFactory(factory.DjangoModelFactory): - FACTORY_FOR = models.User + class UserFactory(factory.django.DjangoModelFactory): + FACTORY_FOR = 'myapp.User' # Equivalent to ``FACTORY_FOR = myapp.models.User`` FACTORY_DJANGO_GET_OR_CREATE = ('username',) username = 'john' @@ -68,3 +72,201 @@ All factories for a Django :class:`~django.db.models.Model` should use the <User: jack> >>> User.objects.all() [<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(MyAbstractModelFactory): + 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` + + .. method:: __init__(self, from_path='', from_file='', data=b'', filename='example.dat') + + :param str from_path: Use data from the file located at ``from_path``, + and keep its filename + :param file from_file: Use the contents of the provided file object; use its filename + if available + :param bytes data: Use the provided bytes as file contents + :param str filename: The filename for the FileField + +.. note:: If the value ``None`` was passed for the :class:`FileField` field, this will + disable field generation: + +.. code-block:: python + + class MyFactory(factory.django.DjangoModelFactory): + FACTORY_FOR = models.MyModel + + the_file = factory.django.FileField(filename='the_file.dat') + +.. code-block:: pycon + + >>> MyFactory(the_file__data=b'uhuh').the_file.read() + b'uhuh' + >>> MyFactory(the_file=None).the_file + None + + +.. class:: ImageField + + Custom declarations for :class:`django.db.models.ImageField` + + .. method:: __init__(self, from_path='', from_file='', filename='example.jpg', width=100, height=100, color='green', format='JPEG') + + :param str from_path: Use data from the file located at ``from_path``, + and keep its filename + :param file from_file: Use the contents of the provided file object; use its filename + if available + :param str filename: The filename for the ImageField + :param int width: The width of the generated image (default: ``100``) + :param int height: The height of the generated image (default: ``100``) + :param str color: The color of the generated image (default: ``'green'``) + :param str format: The image format (as supported by PIL) (default: ``'JPEG'``) + +.. note:: If the value ``None`` was passed for the :class:`FileField` field, this will + disable field generation: + +.. note:: Just as Django's :class:`django.db.models.ImageField` requires the + Python Imaging Library, this :class:`ImageField` requires it too. + +.. code-block:: python + + class MyFactory(factory.django.DjangoModelFactory): + FACTORY_FOR = models.MyModel + + the_image = factory.django.ImageField(color='blue') + +.. code-block:: pycon + + >>> MyFactory(the_image__width=42).the_image.width + 42 + >>> MyFactory(the_image=None).the_image + None + + +Mogo +---- + +.. currentmodule:: factory.mogo + +factory_boy supports `Mogo`_-style models, through the :class:`MogoFactory` class. + +`Mogo`_ is a wrapper around the ``pymongo`` library for MongoDB. + +.. _Mogo: https://github.com/joshmarshall/mogo + +.. class:: MogoFactory(factory.Factory) + + Dedicated class for `Mogo`_ models. + + This class provides the following features: + + * :func:`~factory.Factory.build()` calls a model's ``new()`` method + * :func:`~factory.Factory.create()` builds an instance through ``new()`` then + saves it. + + +MongoEngine +----------- + +.. currentmodule:: factory.mongoengine + +factory_boy supports `MongoEngine`_-style models, through the :class:`MongoEngineFactory` class. + +`mongoengine`_ is a wrapper around the ``pymongo`` library for MongoDB. + +.. _mongoengine: http://mongoengine.org/ + +.. class:: MongoEngineFactory(factory.Factory) + + Dedicated class for `MongoEngine`_ models. + + This class provides the following features: + + * :func:`~factory.Factory.build()` calls a model's ``__init__`` method + * :func:`~factory.Factory.create()` builds an instance through ``__init__`` then + saves it. + + .. note:: If the :attr:`associated class <factory.Factory.FACTORY_FOR>` is a :class:`mongoengine.EmbeddedDocument`, + the :meth:`~MongoEngineFactory.create` function won't "save" it, since this wouldn't make sense. + + This feature makes it possible to use :class:`~factory.SubFactory` to create embedded document. + + +SQLAlchemy +---------- + +.. currentmodule:: factory.alchemy + + +Factoy_boy also supports `SQLAlchemy`_ models through the :class:`SQLAlchemyModelFactory` class. + +To work, this class needs an `SQLAlchemy`_ session object affected to "FACTORY_SESSION" class attribute. + +.. _SQLAlchemy: http://www.sqlalchemy.org/ + +.. class:: SQLAlchemyModelFactory(factory.Factory) + + Dedicated class for `SQLAlchemy`_ models. + + This class provides the following features: + + * :func:`~factory.Factory.create()` uses :meth:`sqlalchemy.orm.session.Session.add` + * :func:`~factory.Factory._setup_next_sequence()` selects the next unused primary key value + + .. attribute:: FACTORY_SESSION + + Fields whose SQLAlchemy session object are passed will be used to communicate with the database + +A (very) simple exemple: + +.. code-block:: python + + from sqlalchemy import Column, Integer, Unicode, create_engine + from sqlalchemy.ext.declarative import declarative_base + from sqlalchemy.orm import scoped_session, sessionmaker + + session = scoped_session(sessionmaker()) + engine = create_engine('sqlite://') + session.configure(bind=engine) + Base = declarative_base() + + + class User(Base): + """ A SQLAlchemy simple model class who represents a user """ + __tablename__ = 'UserTable' + + id = Column(Integer(), primary_key=True) + name = Column(Unicode(20)) + + Base.metadata.create_all(engine) + + + class UserFactory(SQLAlchemyModelFactory): + FACTORY_FOR = User + FACTORY_SESSION = session # the SQLAlchemy session object + + id = factory.Sequence(lambda n: n) + name = factory.Sequence(lambda n: u'User %d' % n) + +.. code-block:: pycon + + >>> session.query(User).all() + [] + >>> UserFactory() + <User: User 1> + >>> session.query(User).all() + [<User: User 1>] |