Skip to content

Commit be95e38

Browse files
Henkhogansheinbergon
authored andcommitted
Allow to opt out from special naming when fieldname ends with _id
1 parent 35b1030 commit be95e38

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ values must be delimited by commas, e.g. ``--options noconstraints,nobidi``):
100100
* ``noconstraints``: ignore constraints (foreign key, unique etc.)
101101
* ``nocomments``: ignore table/column comments
102102
* ``noindexes``: ignore indexes
103+
* ``noidsuffix``: prevent the special naming logic for single column many-to-one
104+
and one-to-one relationships (see `Relationship naming logic`_ for details)
103105

104106
* ``declarative``
105107

src/sqlacodegen/generators.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ class DeclarativeGenerator(TablesGenerator):
729729
"use_inflect",
730730
"nojoined",
731731
"nobidi",
732+
"noidsuffix",
732733
}
733734

734735
def __init__(
@@ -1065,7 +1066,7 @@ def generate_relationship_name(
10651066

10661067
# If there's a constraint with a single column that ends with "_id", use the
10671068
# preceding part as the relationship name
1068-
if relationship.constraint:
1069+
if relationship.constraint and "noidsuffix" not in self.options:
10691070
is_source = relationship.source.table is relationship.constraint.table
10701071
if is_source or relationship.type not in (
10711072
RelationshipType.ONE_TO_ONE,

tests/test_generator_declarative.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,59 @@ class SimpleItems(Base):
14781478
)
14791479

14801480

1481+
@pytest.mark.parametrize("generator", [["noidsuffix"]], indirect=True)
1482+
def test_named_foreign_key_constraints_with_noidsuffix(generator: CodeGenerator) -> None:
1483+
Table(
1484+
"simple_items",
1485+
generator.metadata,
1486+
Column("id", INTEGER, primary_key=True),
1487+
Column("container_id", INTEGER),
1488+
ForeignKeyConstraint(
1489+
["container_id"], ["simple_containers.id"], name="foreignkeytest"
1490+
),
1491+
)
1492+
Table(
1493+
"simple_containers",
1494+
generator.metadata,
1495+
Column("id", INTEGER, primary_key=True),
1496+
)
1497+
1498+
validate_code(
1499+
generator.generate(),
1500+
"""\
1501+
from typing import List, Optional
1502+
1503+
from sqlalchemy import ForeignKeyConstraint, Integer
1504+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
1505+
1506+
class Base(DeclarativeBase):
1507+
pass
1508+
1509+
1510+
class SimpleContainers(Base):
1511+
__tablename__ = 'simple_containers'
1512+
1513+
id: Mapped[int] = mapped_column(Integer, primary_key=True)
1514+
1515+
simple_items: Mapped[List['SimpleItems']] = relationship('SimpleItems', \
1516+
back_populates='simple_containers')
1517+
1518+
1519+
class SimpleItems(Base):
1520+
__tablename__ = 'simple_items'
1521+
__table_args__ = (
1522+
ForeignKeyConstraint(['container_id'], ['simple_containers.id'], \
1523+
name='foreignkeytest'),
1524+
)
1525+
1526+
id: Mapped[int] = mapped_column(Integer, primary_key=True)
1527+
container_id: Mapped[Optional[int]] = mapped_column(Integer)
1528+
1529+
simple_containers: Mapped['SimpleContainers'] = relationship('SimpleContainers', \
1530+
back_populates='simple_items')
1531+
""",
1532+
)
1533+
14811534
# @pytest.mark.xfail(strict=True)
14821535
def test_colname_import_conflict(generator: CodeGenerator) -> None:
14831536
Table(

0 commit comments

Comments
 (0)