Here is my database model (User):
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class SqlAlchemyBase(DeclarativeBase):
"""Base SQL alchemy model."""
class User(SqlAlchemyBase):
"""User database model."""
__tablename__ = "users"
id_: Mapped[uuid] = mapped_column(primary_key=True, index=True, default=uuid.uuid4)
first_name: Mapped[str]
last_name: Mapped[str]
email: Mapped[str] = mapped_column(unique=True, index=True)
hashed_password: Mapped[str]
is_superuser: Mapped[bool]
Here is my factory for the above model:
import factory
import factory.fuzzy
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = User
id_ = factory.Faker("uuid4")
first_name = factory.Faker("first_name")
last_name = factory.Faker("last_name")
email = factory.LazyAttribute(lambda obj: f"{obj.first_name}.{obj.last_name}@gmail.com")
hashed_password = "HashedPwd"
is_superuser = False
How do I create 200 users?
Here are some things I have tried...
Attempt 1:
As per the factory boy documentation here, inside a test function, I tried doing the following:
users = UserFactory().create_batch(200)
But this fails miserably with the following error:
AttributeError: 'User' object has no attribute 'create_batch'
Attempt 2:
I also tried UserFactory().build_batch(200)
but get the same error.
Attempt 3:
Following the docs here
import factory
factory.create_batch(UserFactory, size=200, FACTORY_CLASS=factory.alchemy.SQLAlchemyModelFactory)
This gave me the error:
TypeError: <class 'v1.database.models.test_factories.users.UserFactory'> is already a Factory
Here is what I am using:
Python 3.11
SQLAlchemy~=2.0
factory-boy~=3.3
pytest~=7.4
users = UserFactory().create_batch(200)
should be
users = UserFactory.create_batch(200)
And your email address is not unique, you need to add some random string for your email as well. The following code works for me:
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import create_engine, String
from sqlalchemy.orm import sessionmaker, scoped_session
import uuid
import factory.fuzzy
# Define the database URL and create the engine
DATABASE_URL = "sqlite:///./test.db" # Example database URL
engine = create_engine(DATABASE_URL)
SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
# Define the base model class
class SqlAlchemyBase(DeclarativeBase):
"""Base SQLAlchemy model."""
pass
# Define the User model
class User(SqlAlchemyBase):
"""User database model."""
__tablename__ = "users"
id_: Mapped[uuid.UUID] = mapped_column(primary_key=True, index=True, default=uuid.uuid4, type_=String(36))
first_name: Mapped[str]
last_name: Mapped[str]
email: Mapped[str] = mapped_column(unique=True, index=True)
hashed_password: Mapped[str]
is_superuser: Mapped[bool]
# Create the tables in the database
SqlAlchemyBase.metadata.create_all(bind=engine)
# Define the UserFactory
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = User
sqlalchemy_session = SessionLocal() # Use the session we created
id_ = factory.LazyFunction(lambda: str(uuid.uuid4()))
first_name = factory.Faker("first_name")
last_name = factory.Faker("last_name")
email = factory.LazyAttribute(lambda obj: f"{obj.id_}{obj.first_name}.{obj.last_name}@gmail.com")
hashed_password = "HashedPwd"
is_superuser = False
# Create a batch of users and commit them to the database
session = SessionLocal()
users = UserFactory.create_batch(200)
session.commit() # Commit the changes to the database
session.close() # Close the session