What is the correct way to use factory boy with Flask-SQLAlchemy and Foreign Key constraints?
Consider the following Flask SQLAlchemy Model setup:
# coding=utf-8
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
# ------------------------------
# SQLAlchemy Table Models
# ------------------------------
class User(db.Model):
""" A SQLAlchemy simple model class who represents a user with a ForeignKey Constraint"""
__tablename__ = 'UserTable'
user_pk = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.Unicode(20))
group_fk = db.Column(db.ForeignKey("GroupTable.group_pk"), nullable=False)
class Group(db.Model):
""" A SQLAlchemy simple model class who represents a user """
__tablename__ = 'GroupTable'
group_pk = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(), nullable=False)
# -------------------------
# Create the SQL tables
# -------------------------
db.create_all()
The User schema requires a Group foreign key when creating a new user. Since the Group primary key is assigned from the database, the factory would need to commit a group entry and get the entry's primary key so that it can provide it to the new User.
How do I create a group, save it to the DB, and provide it's key to the User Factory?
Factory Boy has examples for dealing with Foreign Keys but they don't seem to apply to SQLAlchemy. Here are the factories and the failure point:
# ----------------------------------------
# Factory-Boy User and Group Factories
# ----------------------------------------
from factory import alchemy, Sequence, RelatedFactory
class GroupFactory(alchemy.SQLAlchemyModelFactory):
class Meta(object):
model = Group
sqlalchemy_session = db.session # the SQLAlchemy session object
name = Sequence(lambda n: "Group {}".format(n))
# group_pk = Sequence(lambda n: n)
class UserFactory(alchemy.SQLAlchemyModelFactory):
class Meta(object):
model = User
sqlalchemy_session = db.session # the SQLAlchemy session object
user_pk = Sequence(lambda n: n)
name = Sequence(lambda n: u'User %d' % n) # coding=utf-8
group_fk = RelatedFactory(GroupFactory)
# ----------------------
# Factory tests
# ----------------------
# Create a new Group from our factory
group_from_factory = GroupFactory(name='a new group name')
assert group_from_factory.group_pk is None
# Save it to our DB
db.session.add(group_from_factory)
db.session.commit()
# Verify that Group Saved correctly to DB
group_from_db = db.session.query(Group).filter(Group.group_pk == group_from_factory.group_pk).first()
assert group_from_db.group_pk is not None
assert group_from_db.name == 'a new group name'
assert group_from_db.group_pk == group_from_factory.group_pk
# Create a new User from our factory
user_from_factory = UserFactory()
db.session.add(user_from_factory)
# ----------------------------------------------
# FAILS AT COMMIT() - NOT NULL constraint failed (group_fk is null)
# ----------------------------------------------
db.session.commit()
assert user_from_factory.user_pk is not None
assert user_from_factory.name is not None
assert user_from_factory.group_fk is not None