Was ist der richtige Weg, Factory Boy mit Flask-SQLAlchemy und Foreign Key Einschränkungen zu verwenden?Wie richte ich abhängige Fabriken mit Factory Boy und Flask-SQLAlchemy ein?
Betrachten Sie das folgende Flask SQLAlchemy Modell 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()
Der Nutzer Schema erfordert eine Gruppe Fremdschlüssel beim Anlegen eines neuen Benutzers. Da der Gruppenprimärschlüssel aus der Datenbank zugewiesen wird, muss die Factory einen Gruppeneintrag festschreiben und den Primärschlüssel des Eintrags abrufen, damit dieser dem neuen Benutzer bereitgestellt werden kann.
Wie erstelle ich eine Gruppe, speichere sie in der DB und lege sie der User Factory zur Verfügung?
Factory Boy has examples for dealing with Foreign Keys, aber sie scheinen nicht für SQLAlchemy gelten. Hier sind die Fabriken und die Fehlerpunkt:
# ----------------------------------------
# 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
** ** SubFactory funktioniert nicht. Siehe dazu Kommentare. Laut dem Factory Boy api sollte es, aber das tut es nicht, weshalb ich darauf gepostet habe. – etiology