杰瑞科技汇

如何用Python sqlacodegen生成ORM模型?

Of course! sqlacodegen is an incredibly useful command-line tool that automatically generates Python model code for SQLAlchemy from an existing database. It saves you a massive amount of time when you need to reverse-engineer a database schema.

如何用Python sqlacodegen生成ORM模型?-图1
(图片来源网络,侵删)

Here’s a complete guide covering what it is, why you'd use it, how to install and run it, and how to interpret the output.


What is sqlacodegen?

sqlacodegen is a tool that introspects a database (by connecting to it) and reads its schema (tables, columns, data types, relationships, indexes, etc.). It then generates Python code that defines these tables as SQLAlchemy ORM (Object-Relational Mapping) models.

In short, it turns a database schema into a Python file you can use in your application.

Why Use It?

  1. Rapid Prototyping: Get a basic ORM model for an existing database in seconds, allowing you to start building your application immediately.
  2. Legacy Database Integration: When you're handed a database with no existing Python code, sqlacodegen provides a solid starting point for your models.
  3. Documentation: The generated code serves as a clear, machine-readable representation of your database structure.
  4. Learning: It's a great way to see how complex database schemas (like those with foreign keys and many-to-many relationships) are represented in SQLAlchemy.

Step 1: Installation

First, you need to install sqlacodegen. It's available on PyPI.

如何用Python sqlacodegen生成ORM模型?-图2
(图片来源网络,侵删)
pip install sqlacodegen

You will also need a database driver for the specific database you're connecting to. For example:

  • PostgreSQL: pip install psycopg2-binary
  • MySQL: pip install PyMySQL or pip install mysql-connector-python
  • SQLite: pip install pysqlite3 (or use the built-in sqlite3)
  • SQL Server: pip install pymssql

Step 2: Basic Usage

The command structure is simple:

sqlacodegen <database_uri> > models.py

Let's break this down:

  • sqlacodegen: The command you run.
  • <database_uri>: The connection string to your database. This is the most important part.
  • >: A shell redirect operator. It takes the output from the command and writes it into a file.
  • models.py: The name of the output file where the generated code will be saved.

Database URI Examples

The format of the database URI depends on the database you're using.

Database Example URI
SQLite sqlite:///path/to/your/database.db (Three slashes for a relative path)
sqlite:////absolute/path/to/your/database.db (Four slashes for an absolute path)
PostgreSQL postgresql://user:password@host:port/database_name
MySQL mysql+pymysql://user:password@host:port/database_name
SQL Server mssql+pymssql://user:password@host:port/database_name

Step 3: A Complete Example with SQLite

Let's walk through a full example.

Create a Sample SQLite Database

First, let's create a simple database with a couple of tables and some relationships.

# setup_db.py
import sqlite3
# Connect to the database (it will be created if it doesn't exist)
conn = sqlite3.connect('my_database.db')
cursor = conn.cursor()
# Create a 'users' table
cursor.execute('''
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL,
    full_name TEXT
)
''')
# Create a 'posts' table
cursor.execute('''
CREATE TABLE posts (
    id INTEGER PRIMARY KEY,TEXT NOT NULL,
    content TEXT,
    user_id INTEGER,
    FOREIGN KEY (user_id) REFERENCES users (id)
)
''')
# Create a 'tags' table
cursor.execute('''
CREATE TABLE tags (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL UNIQUE
)
''')
# Create a 'post_tags' junction table for a many-to-many relationship
cursor.execute('''
CREATE TABLE post_tags (
    post_id INTEGER,
    tag_id INTEGER,
    PRIMARY KEY (post_id, tag_id),
    FOREIGN KEY (post_id) REFERENCES posts (id),
    FOREIGN KEY (tag_id) REFERENCES tags (id)
)
''')
# Commit the changes and close the connection
conn.commit()
conn.close()
print("Database 'my_database.db' created successfully.")

Run this script to generate my_database.db.

Run sqlacodegen

Now, run the generator on the database you just created.

sqlacodegen sqlite:///my_database.db > models.py

Inspect the Generated models.py

The tool will create a models.py file. Here is what it will look like, with explanations for each part.

# models.py
from sqlalchemy import Column, ForeignKey, Integer, String, Table
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
metadata = Base.metadata
# This is the "junction table" for the many-to-many relationship.
# It's automatically detected and created as a Table object.
t_post_tags = Table(
    'post_tags', metadata,
    Column('post_id', Integer, ForeignKey('posts.id')),
    Column('tag_id', Integer, ForeignKey('tags.id'))
)
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    username = Column(String, nullable=False, unique=True)
    email = Column(String, nullable=False)
    full_name = Column(String)
    # This defines the one-to-many relationship: one User can have many Posts.
    # The `back_populates` ensures the relationship is two-way.
    posts = relationship("Post", back_populates="user")
class Post(Base):
    __tablename__ = 'posts'
    id = Column(Integer, primary_key=True)= Column(String, nullable=False)
    content = Column(String)
    user_id = Column(Integer, ForeignKey('users.id'))
    # This is the "many" side of the one-to-many relationship.
    # It links back to the User.
    user = relationship("User", back_populates="posts")
    # This defines the many-to-many relationship: a Post can have many Tags.
    # The `secondary` argument points to our junction table.
    tags = relationship("Tag", secondary=t_post_tags, back_populates="posts")
class Tag(Base):
    __tablename__ = 'tags'
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False, unique=True)
    # This is the other side of the many-to-many relationship.
    # It links back to the Post.
    posts = relationship("Post", secondary=t_post_tags, back_populates="tags")

Key Takeaways from the Output:

  • Base = declarative_base(): This is the standard base class for your SQLAlchemy ORM models.
  • __tablename__ = 'users': Each class corresponds to a database table.
  • Column(...): Each attribute in the class is a column, with its type (Integer, String) and constraints (primary_key=True, nullable=False, unique=True).
  • ForeignKey(...): This correctly identifies foreign key relationships.
  • relationship(...): This is the magic of SQLAlchemy ORM. It defines how tables relate to each other.
    • One-to-Many (User -> Post): The User has a posts relationship, and the Post has a user relationship. back_populates links them together.
    • Many-to-Many (Post <-> Tag): The tool correctly identifies the junction table (post_tags) and uses the secondary argument in the relationship() to define the link. Both Post and Tag have a relationship back to each other.

Advanced Options and Flags

sqlacodegen offers several useful flags to customize the output.

You can see all options by running sqlacodegen --help.

Here are some of the most common ones:

Flag Description Example
--tables Generate models for only the specified tables. sqlacodegen --tables users,posts sqlite:///my_database.db
--schema Specify a schema name (useful for PostgreSQL). sqlacodegen --schema public postgresql://...
--no-constraints Do not generate primary_key, nullable, or unique constraints. sqlacodegen --no-constraints sqlite:///...
--no-engine Do not generate the create_engine() call. sqlacodegen --no-engine sqlite:///...
--flask Generate Flask-SQLAlchemy models (uses db.Model instead of Base). sqlacodegen --flask sqlite:///...
--novel Generate a more modern, "novel" style of SQLAlchemy 2.0 code. sqlacodegen --novel sqlite:///...

Example: Generating for Specific Tables

If your database is huge and you only need a few tables, this is a huge time-saver.

# Only generate the User and Post models
sqlacodegen --tables users,posts sqlite:///my_database.db > user_post_models.py

This will produce a much smaller file containing only the User and Post classes and their relationship.

分享:
扫描分享到社交APP
上一篇
下一篇