polyfactory icon indicating copy to clipboard operation
polyfactory copied to clipboard

Docs: specify the compatibility with SQLModel more explicitely

Open ddahan opened this issue 1 year ago • 1 comments

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:

  • Is SQLModel supported?
  • If not directly, is there a workaround?
  • Is is possible to provide some documentation about it? I guess it would valuable for people coming from fastAPI (with SQLModel) to know if they should stick to factory-boy or not, or can use a more modern approach like polyfactory.

Thanks! Keep up the great work.

ddahan avatar Sep 19 '24 13:09 ddahan

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

adhtruong avatar Sep 21 '24 08:09 adhtruong