diff --git a/src/marshmallow_sqlalchemy/convert.py b/src/marshmallow_sqlalchemy/convert.py index 2e080df9..a3c1a585 100644 --- a/src/marshmallow_sqlalchemy/convert.py +++ b/src/marshmallow_sqlalchemy/convert.py @@ -348,7 +348,7 @@ def _add_relationship_kwargs(self, kwargs, prop): nullable = True for pair in prop.local_remote_pairs: if not pair[0].nullable: - if prop.uselist is True: + if prop.uselist is True or prop.direction.name == "MANYTOONE": nullable = False break kwargs.update({"allow_none": nullable, "required": not nullable}) diff --git a/tests/conftest.py b/tests/conftest.py index 51e237d7..ae0881d7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -194,7 +194,7 @@ class Lecture(Base): seminar = relationship( Seminar, foreign_keys=[seminar_title, seminar_semester], backref="lectures" ) - kw = relationship("Keyword", secondary=lecturekeywords_table) + kw = relationship("Keyword", uselist=False, secondary=lecturekeywords_table) keywords = association_proxy( "kw", "keyword", creator=lambda kw: Keyword(keyword=kw) ) diff --git a/tests/test_conversion.py b/tests/test_conversion.py index deffcc02..fb193135 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -354,6 +354,49 @@ class ModelWithArray(Base): assert field.dump_only is True +class TestRelationShipKwarg: + def test_many_to_one_relationship_kwarg(self, models): + default_converter = ModelConverter() + + rel = models.Student.__mapper__.get_property("current_school") + assert rel.direction.name == "MANYTOONE" + assert rel.uselist is False + rel_kwargs = {} + default_converter._add_relationship_kwargs(rel_kwargs, rel) + assert rel_kwargs["allow_none"] is False + assert rel_kwargs["required"] is True + + rel = models.School.__mapper__.get_property("students") + assert rel.direction.name == "ONETOMANY" + assert rel.uselist is True + rel_kwargs = {} + default_converter._add_relationship_kwargs(rel_kwargs, rel) + assert rel_kwargs["allow_none"] is False + assert rel_kwargs["required"] is True + + def test_many_to_many_with_uselist_relationship_kwarg(self, models): + default_converter = ModelConverter() + + rel = models.Student.__mapper__.get_property("courses") + assert rel.direction.name == "MANYTOMANY" + assert rel.uselist is True + rel_kwargs = {} + default_converter._add_relationship_kwargs(rel_kwargs, rel) + assert rel_kwargs["allow_none"] is False + assert rel_kwargs["required"] is True + + def test_many_to_many_without_uselist_relationship_kwarg(self, models): + default_converter = ModelConverter() + + rel = models.Lecture.__mapper__.get_property("kw") + assert rel.direction.name == "MANYTOMANY" + assert rel.uselist is False + rel_kwargs = {} + default_converter._add_relationship_kwargs(rel_kwargs, rel) + assert rel_kwargs["allow_none"] is True + assert rel_kwargs["required"] is False + + def _repr_validator_list(validators): return sorted(repr(validator) for validator in validators)