litestar-org / polyfactory

Simple and powerful factories for mock data generation
https://polyfactory.litestar.dev/
MIT License
1.05k stars 81 forks source link

Docs: specify the compatibility with SQLModel more explicitely #586

Open ddahan opened 1 month ago

ddahan commented 1 month ago

Summary

Hi there. After browsing the documentation (and some issues/PR), I'm still not sure if SQLModel is properly supported at this time. SQLModel objects have the particularity to be both Pydantic and SQLAlchemy objects, so in theory, it may work using SQLAlchemyFactory.

But after trying by myself with this code:

import secrets

from polyfactory import Use
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory
from sqlmodel import Field, Relationship, SQLModel

def get_random_id() -> str:
    return secrets.token_urlsafe(nbytes=16)

class Place(SQLModel, table=True):
    id: str = Field(default_factory=get_random_id, primary_key=True)
    name: str = Field(unique=True)
    items: list["Item"] = Relationship(back_populates="place")

class Item(SQLModel, table=True):
    id: str = Field(default_factory=get_random_id, primary_key=True)
    name: str = Field(unique=True)
    place_id: str = Field(default=None, foreign_key="place.id")
    place: Place = Relationship(back_populates="items")

class PlaceFactory(SQLAlchemyFactory[Place]):
    __set_relationships__ = True

class ItemFactory(SQLAlchemyFactory[Item]):
    __set_relationships__ = True
    place = Use(PlaceFactory.build)

def test_factories():
    item = ItemFactory.build()
    assert item.place_id == item.place.id  #  /!\ AssertionError, they are not the same

With this code, the relationship is not actually created with the factory. I guess it's because polyfactory does not detect the Relationship() field which is specific to SQLModel.

So:

Thanks! Keep up the great work.


[!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 commented 1 month ago

Hi ddahan, this should work in most situations for SQLModel though may be some edges cases not supported.

The current behaviour for SQLAlchemyFactory is to not resolve foreign keys by default to avoid adding this complexity to this library itself. Using the example here and using a persistence handler so SQLA resolves these references should fix the example