Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLAlchemyFactory with foreign keys #551

Closed
vickypalani opened this issue May 17, 2024 · 3 comments
Closed

SQLAlchemyFactory with foreign keys #551

vickypalani opened this issue May 17, 2024 · 3 comments

Comments

@vickypalani
Copy link

vickypalani commented May 17, 2024

Hi, I'm facing some trouble while creating factories that involve ForeignKeys in SQLAlchemy...

class EmailCategory(SoftDeleteMixin, BaseModal):

    __tablename__ = "email_categories"

    id = Column(Integer, primary_key=True)
    name = Column(String(255), unique=True, nullable=False)
    email_templates = relationship("EmailTemplate", back_populates="category")

class EmailTemplate(SoftDeleteMixin, BaseModal):

    __tablename__ = "email_templates"

    id = Column(Integer, primary_key=True)
    name = Column(String(255), unique=True, nullable=False)
    subject = Column(String(255), nullable=False)
    body = Column(Text, nullable=False)
    category_id = Column(
        Integer, ForeignKey("email_categories.id", ondelete="CASCADE"), nullable=False
    )
    category = relationship("EmailCategory", back_populates="email_templates")


class AsyncPersistenceHandler(AsyncPersistenceProtocol[T]):
    async def save(self, data: T) -> T:
        async with get_db_context() as session:
            session.add(data)
            await session.commit()

    async def save_many(self, data: List[T]) -> List[T]:
        async with get_db_context() as session:
            session.add_all(data)
            await session.commit()


class BaseFactory(SQLAlchemyFactory):
    """Base Faactory"""

    __is_base_factory__ = True
    __async_persistence__ = AsyncPersistenceHandler

    id = Ignore()
    deleted_at = None
    created_at = Use(lambda: datetime.now())


class EmailCategoryFactory(BaseFactory):
    """Factory for generating EmailCategory dummy data."""

    __model__ = EmailCategory
    name = Use(lambda: EmailCategoryFactory.__faker__.user_name())


class EmailTemplateFactory(BaseFactory):
    """Factory for generating EmailTemplate dummy data."""

    __model__ = EmailTemplate
    category = EmailCategoryFactory


async def _main():
    template = await EmailTemplateFactory.create_async()
    print(template)


if __name__ == "__main__":
    asyncio.run(_main())

When I try to create an EmailCategory model instance, I get an IntegrityError mentioning that the random integer assigned to foreign key field is not present in the table "email_categories" (which is expected). Right now I'm passing the foreign_key values manually, like this

    category = await EmailCategoryFactory.create_async()
    template = await EmailTemplateFactory.create_async(category_id=category.id)
    print(template)

Is there any other way to implement the same?


Note

While we are open for sponsoring on GitHub Sponsors and
OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh dashboard

  • If you would like to see an issue prioritized, make a pledge towards it!
  • We receive the pledge once the issue is completed & verified
  • This, along with engagement in the community, helps us know which features are a priority to our users.
Fund with Polar
@adhtruong
Copy link
Collaborator

adhtruong commented May 20, 2024

Hi @vickypalani, could you try adding adding __set_relationships__? Docs here. By default these, relationships are not set as these causes some issues with recursive relationships originally.

@guacs
Copy link
Member

guacs commented May 26, 2024

@vickypalani I think the solution mentioned above should work. If not, feel free to reopen the issue.

@guacs guacs closed this as not planned Won't fix, can't repro, duplicate, stale May 26, 2024
@vickypalani
Copy link
Author

Hi @adhtruong thanks for the response, @guacs sorry for not updating the status of the issue. I was able to resolve this after going through the documentation last week. This is how my factory looks right now,

class EmailTemplateFactory(BaseFactory):
    """Factory for generating EmailTemplate dummy data."""

    __model__ = EmailTemplate
    __set_relationships__ = True
    category = EmailCategoryFactory
    created_by = UserFactory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants