SQLAlchemyFactory
=================

Basic usage is like other factories

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_1.py
    :caption: Declaring a factory for a SQLAlchemy model
    :language: python

.. note::
    The examples here require SQLAlchemy 2 to be installed. The factory itself supports both 1.4 and 2.


Configuration
-------------

SQLAlchemyFactory allows to override some configuration attributes so that a described factory can use a behavior from SQLAlchemy ORM such as `relationship() <https://docs.sqlalchemy.org/en/20/orm/relationship_api.html#sqlalchemy.orm.relationship>`_ or `Association Proxy <https://docs.sqlalchemy.org/en/20/orm/extensions/associationproxy.html#module-sqlalchemy.ext.associationproxy>`_.

Relationship
++++++++++++

By default, ``__set_relationships__`` is set to ``True``. If it is ``True``, all fields with the SQLAlchemy `relationship() <relationship()_>`_ will be included in the result created by ``build`` method.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_2.py
    :caption: Setting relationships
    :language: python

.. note::
    If ``__set_relationships__ = True``, ForeignKey fields associated with relationship() will be automatically generated by ``build`` method because :class:`__set_foreign_keys__ <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory.__set_foreign_keys__>` is set to ``True`` by default. But their values will be overwritten by using ``create_sync``/ ``create_async`` methods, so SQLAlchemy ORM creates them.

.. note::
    The default for `__set_relationships__` is changed to `True` in v3. Set explicitly to retain existing behaviour.

Association Proxy
+++++++++++++++++

By default, ``__set_association_proxy__`` is set to ``True``. If it is ``True``, all SQLAlchemy fields mapped to ORM `Association Proxy <Association Proxy_>`_ class will be included in the result created by ``build`` method.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_association_proxy.py
    :caption: Setting association_proxy
    :language: python

.. note::
    If ``__set_association_proxy__ = True``, the Polyfactory will create both fields from a particular SQLAlchemy model (association_proxy and its relationship), but eventually a relationship field will be overwritten by using ``create_sync``/ ``create_async`` methods via SQLAlchemy ORM with a proper instance from an Association Proxy relation.

.. note::
    The default for `__set_association_proxy__` is changed to `True` in v3. Set explicitly to retain existing behaviour.


Persistence
-----------

A handler is provided to allow persistence. This can be used by setting ``__session__`` attribute on a factory.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_3.py
    :caption: Using persistence
    :language: python

By default, this will add generated models to the session and then commit. This can be customised further by setting ``__sync_persistence__``.

Similarly for ``__async_session__`` and ``create_async``.

Persistence Method
++++++++++++++++++

By default, the factory uses ``commit()`` to persist data, which permanently saves changes to the database. You can configure the factory to use ``flush()`` instead by setting ``__persistence_method__`` to ``SQLAlchemyPersistenceMethod.FLUSH``.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_persistence_method.py
    :caption: Using flush() vs commit() for persistence
    :language: python


Adding global overrides
-----------------------

By combining the above and using other settings, a global base factory can be set up for other factories.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_4.py
    :caption: Using persistence
    :language: python


Add column type mapping
-----------------------

Columns types and normally automatically mapped to Python type. This can be overridden for cases where Python type is not available or need to provide extra information to correctly generate.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_5.py
    :caption: Overriding SQLA column type mapping
    :language: python

API reference
-------------
Full API docs are available :class:`here <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory>`.
