Using factory_boy with ORMs¶
factory_boy provides custom Factory
subclasses for various ORMs,
adding dedicated features.
Django¶
The first versions of factory_boy were designed specifically for Django, but the library has now evolved to be framework-independant.
Most features should thus feel quite familiar to Django users.
The DjangoModelFactory
subclass¶
All factories for a Django Model
should use the
DjangoModelFactory
base class.
-
class
factory.django.
DjangoModelFactory
(factory.Factory)[source]¶ Dedicated class for Django
Model
factories.This class provides the following features:
- The
model
attribute also supports the'app.Model'
syntax create()
usesModel.objects.create()
_setup_next_sequence()
selects the next unused primary key value- When using
RelatedFactory
orPostGeneration
attributes, the base object will besaved
once all post-generation hooks have run.
-
FACTORY_DJANGO_GET_OR_CREATE
¶ Deprecated since version 2.4.0: See
DjangoOptions.django_get_or_create
.
- The
-
class
factory.django.
DjangoOptions
(factory.base.FactoryOptions)[source]¶ The
class Meta
on aDjangoModelFactory
supports an extra parameter:-
django_get_or_create
¶ New in version 2.4.0.
Fields whose name are passed in this list will be used to perform a
Model.objects.get_or_create()
instead of the usualModel.objects.create()
:class UserFactory(factory.django.DjangoModelFactory): class Meta: model = 'myapp.User' # Equivalent to ``model = myapp.models.User`` django_get_or_create = ('username',) username = 'john'
>>> User.objects.all() [] >>> UserFactory() # Creates a new user <User: john> >>> User.objects.all() [<User: john>] >>> UserFactory() # Fetches the existing user <User: john> >>> User.objects.all() # No new user! [<User: john>] >>> UserFactory(username='jack') # Creates another user <User: jack> >>> User.objects.all() [<User: john>, <User: jack>]
-
Note
If a DjangoModelFactory
relates to an abstract
model, be sure to declare the DjangoModelFactory
as abstract:
class MyAbstractModelFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.MyAbstractModel
abstract = True
class MyConcreteModelFactory(MyAbstractModelFactory):
class Meta:
model = models.MyConcreteModel
Otherwise, factory_boy will try to get the ‘next PK’ counter from the abstract model.
Extra fields¶
-
class
factory.django.
FileField
[source]¶ Custom declarations for
django.db.models.FileField
-
__init__
(self, from_path='', from_file='', data=b'', filename='example.dat')[source]¶ Parameters: - from_path (str) – Use data from the file located at
from_path
, and keep its filename - from_file (file) – Use the contents of the provided file object; use its filename if available
- data (bytes) – Use the provided bytes as file contents
- filename (str) – The filename for the FileField
- from_path (str) – Use data from the file located at
-
Note
If the value None
was passed for the FileField
field, this will
disable field generation:
class MyFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.MyModel
the_file = factory.django.FileField(filename='the_file.dat')
>>> MyFactory(the_file__data=b'uhuh').the_file.read()
b'uhuh'
>>> MyFactory(the_file=None).the_file
None
-
class
factory.django.
ImageField
[source]¶ Custom declarations for
django.db.models.ImageField
-
__init__
(self, from_path='', from_file='', filename='example.jpg', width=100, height=100, color='green', format='JPEG')¶ Parameters: - from_path (str) – Use data from the file located at
from_path
, and keep its filename - from_file (file) – Use the contents of the provided file object; use its filename if available
- filename (str) – The filename for the ImageField
- width (int) – The width of the generated image (default:
100
) - height (int) – The height of the generated image (default:
100
) - color (str) – The color of the generated image (default:
'green'
) - format (str) – The image format (as supported by PIL) (default:
'JPEG'
)
- from_path (str) – Use data from the file located at
-
Note
If the value None
was passed for the FileField
field, this will
disable field generation:
Note
Just as Django’s django.db.models.ImageField
requires the
Python Imaging Library, this ImageField
requires it too.
class MyFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.MyModel
the_image = factory.django.ImageField(color='blue')
>>> MyFactory(the_image__width=42).the_image.width
42
>>> MyFactory(the_image=None).the_image
None
Disabling signals¶
Signals are often used to plug some custom code into external components code;
for instance to create Profile
objects on-the-fly when a new User
object is saved.
This may interfere with finely tuned factories
, which would
create both using RelatedFactory
.
To work around this problem, use the mute_signals()
decorator/context manager:
-
factory.django.
mute_signals
(signal1, ...)[source]¶ Disable the list of selected signals when calling the factory, and reactivate them upon leaving.
# foo/factories.py
import factory
import factory.django
from . import models
from . import signals
@factory.django.mute_signals(signals.pre_save, signals.post_save)
class FooFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Foo
# ...
def make_chain():
with factory.django.mute_signals(signals.pre_save, signals.post_save):
# pre_save/post_save won't be called here.
return SomeFactory(), SomeOtherFactory()
Mogo¶
factory_boy supports Mogo-style models, through the MogoFactory
class.
Mogo is a wrapper around the pymongo
library for MongoDB.
MongoEngine¶
factory_boy supports MongoEngine-style models, through the MongoEngineFactory
class.
mongoengine is a wrapper around the pymongo
library for MongoDB.
-
class
factory.mongoengine.
MongoEngineFactory
(factory.Factory)[source]¶ Dedicated class for MongoEngine models.
This class provides the following features:
Note
If the
associated class <factory.FactoryOptions.model
is amongoengine.EmbeddedDocument
, thecreate()
function won’t “save” it, since this wouldn’t make sense.This feature makes it possible to use
SubFactory
to create embedded document.
SQLAlchemy¶
Factoy_boy also supports SQLAlchemy models through the SQLAlchemyModelFactory
class.
To work, this class needs an SQLAlchemy session object affected to the Meta.sqlalchemy_session
attribute.
-
class
factory.alchemy.
SQLAlchemyModelFactory
(factory.Factory)[source]¶ Dedicated class for SQLAlchemy models.
This class provides the following features:
create()
usessqlalchemy.orm.session.Session.add()
_setup_next_sequence()
selects the next unused primary key value
-
FACTORY_SESSION
¶ Deprecated since version 2.4.0: See
sqlalchemy_session
.
-
class
factory.alchemy.
SQLAlchemyOptions
(factory.base.FactoryOptions)[source]¶ In addition to the usual parameters available in
class Meta
, aSQLAlchemyModelFactory
also supports the following settings:-
sqlalchemy_session
¶ SQLAlchemy session to use to communicate with the database when creating an object through this
SQLAlchemyModelFactory
.
-
A (very) simple exemple:
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):
class Meta:
model = User
sqlalchemy_session = session # the SQLAlchemy session object
id = factory.Sequence(lambda n: n)
name = factory.Sequence(lambda n: u'User %d' % n)
>>> session.query(User).all()
[]
>>> UserFactory()
<User: User 1>
>>> session.query(User).all()
[<User: User 1>]