Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sqlacodegen generates mixed models and tables

Executing this command:

sqlacodegen <connection-url> --outfile db.py 

The db.py contains generated tables:

t_table1 = Table(...)

and classes too:

Table2(Base):
    __tablename__ = 'table2'

The problem is that a table is generated in one way only - either a table or a class.

I would like to make it generate models (classes) only but in the provided flags I couldn't find such an option. Any idea?

like image 394
Amio.io Avatar asked Jan 08 '16 11:01

Amio.io


1 Answers

It looks like what you're describing is a feature itself. sqlacodegenwill not always generate class models.

It will only form model classes for tables that have a primary key and are not association tables, as you can see in the source code:

# Only form model classes for tables that have a primary key and are not association tables
if noclasses or not table.primary_key or table.name in association_tables:
    model = self.table_model(table)
else:
    model = self.class_model(table, links[table.name], self.inflect_engine, not nojoined)
    classes[model.name] = model

Furthermore, in the documentation it is stated that

A table is considered an association table if it satisfies all of the following conditions:

  1. has exactly two foreign key constraints
  2. all its columns are involved in said constraints

Although, you can try a quick and dirty hack. Locate those lines in the source code (something like /.../lib/python2.7/site-packages/sqlacodegen/codegen.py) and comment out the first three code lines (and fix indentation):

# Only form model classes for tables that have a primary key and are not association tables
# if noclasses or not table.primary_key or table.name in association_tables:
#    model = self.table_model(table)
# else:
model = self.class_model(table, links[table.name], self.inflect_engine, not nojoined)
classes[model.name] = model

I have tried this for one specific table that was generated as a table model. It went from

t_Admin_op = Table(
    'Admin_op', metadata,
    Column('id_admin', Integer, nullable=False),
    Column('id_op', Integer, nullable=False)
)

to

class AdminOp(Base):
    __tablename__ = 'Admin_op'

    id_admin = Column(Integer, nullable=False)
    id_op = Column(Integer, nullable=False)

You can also open an issue about this as a feature request, in the official tracker.

Just in case, if you want the opposite (only table models), you could do so with the --noclasses flag.

like image 139
iled Avatar answered Oct 30 '22 04:10

iled