跳转到主要内容

在运行时将sqlalchemy数据库模式转换为django数据库模型。

项目描述

SqlAlchemy到Django桥梁

在运行时将sqlalchemy数据库模式转换为django数据库模型。

原始链接: https://github.com/mariushelf/sa2django

SqlAlchemy到Django桥梁允许您在SqlAlchemy中指定数据模型,并在Django中使用它们,而无需手动重新指定所有模型和字段以供Django ORM使用。

为什么使用这个包?

在SqlAlchemy中指定模式然后将其用于Django听起来似乎... 反直觉。有很多 为什么不 要回答...

为什么不直接在Django中指定模型?

有时,从Django提供的一些或全部数据由不属于Django应用程序的来源维护或创建。如果这些来源已经指定了完整的SqlAlchemy模型,那么SqlAlchemy到Django桥梁是有用的。

为什么不简单地使用inspectdb来动态生成Django模型规范?

inspectdb 并非真正动态 -- 它一次生成一个Python文件,需要手动修改。每次数据模型发生变化时,都需要调整该Python文件。

此外,通常无法从数据库中自动推导出模型之间的所有关系。对于第三方数据源,关系通常不表现为数据库模式中的外键约束,而是在一些文档中解释这些关系,这些文档以人类可读但不适合机器阅读的形式解释这些关系。

如果SqlAlchemy模型已经包含所有这些关系,那么在运行时将SqlAlchemy模型转换为Django ORM是有意义的。

状态

SQLAlchemy到Django的桥接器在作者的用例中运行良好。

可能存在许多边界情况和SQLAlchemy的许多(或不那么复杂)的功能尚未(尚不支持)。

测试在sqlite中运行,我们的生产系统使用PostgreSQL。它可能或不与其它数据库系统兼容。

安装

pip install sa2django

特性

  • 基本数据类型(int,float,字符串,varchar,char,日期,datetime等,bytea)
  • 外键和一对多关系
  • 包括through表的一对多关系
  • 自动推断sqlalchemy Base中声明的所有模型
  • 或者按照常规定义Django模型,但使用SA2DModel作为基类。然后所有数据库字段都将从相应的sqlalchemy模型中添加,但您仍然可以向Django模型添加属性和函数

用法

定义您的SQLAlchemy模式

假设您有以下SQLAlchemy模式

# sqlalchemy_schema.py
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

class Parent(Base):
    __tablename__ = "parent"
    id = Column(Integer, primary_key=True)
    name = Column(String)
    children = relationship("Child", back_populates="parent")


class Child(Base):
    __tablename__ = "child"
    id = Column(Integer, primary_key=True)
    name = Column(String)
    age = Column(Integer)
    parent_id = Column(Integer, ForeignKey("parent.id"))
    parent = relationship(Parent, uselist=False, back_populates="children")

自动推断

您可以通过将以下代码添加到您的models.py来在Django应用程序中使用它

# models.py
from sa2django.core import generate_sa2d_models, inject_models
from sqlalchemy_models import Base  # this is what we have specified in the snippet above

_models = generate_sa2d_models(Base, __name__)
inject_models(_models, globals())

这将把类ChildParent添加到您的models模块中。这些类是与SQLAlchemy模型相对应的Django模型。

您在文件中看不到它们,但Django会识别它们,您可以在应用程序的任何地方导入它们,就像您手动声明了它们一样

from models import Parent, Child

print(Child.objects.all())
child = Child.objects.get(pk=my_pk)
print(child.parents.all())

注意:您的IDE可能会抱怨,因为它认为ParentChild不存在。它不知道,因为类是在运行时创建的。代码将正常运行。

手动指定和自定义属性

Django的一个优点是它允许在模型上指定额外的属性。sa2django支持这一点。为此,您可以显式声明您的模型,并从sa2django.SA2DModel继承,而不是从django.db.models.Model继承,并在Meta类下sa_model属性中指定相应的SQLAlchemy模型。

您还需要使用register_table()注册由SQLAlchemy模式中的任何模型引用的所有Django模型。

然后您就有控制权,可以控制类名和额外的属性,并仅使用sa2django将所有字段和关系添加到您的Django模型中。

以下是一个示例

from sa2django import register_table, SA2DModel
from sa2django.core import extract_tables_from_base
import sqlalchemy_models

# extract all SQLAlchemy tables
_tables = extract_tables_from_base(sqlalchemy_models.Base)

# register the tables
for _tablename, _sa_class in _tables.items():
    register_table(_tablename, _sa_class.__name__)

class Child(SA2DModel):
    class Meta:
        sa_model = sqlalchemy_models.Child
        ordering = ["age"]
    
    @property
    def age_next_year(self):
        return self.age + 1

class Parent(SA2DModel):
    class Meta:
        sa_model = sqlalchemy_models.Parent

目前不能混合手动和自动模型提取--如果您手动指定了一个模型,则不能再使用generate_sa2d_models(),因此您需要手动指定所有模型。

限制

SQLAlchemy提供了Django功能的超集。因此,有一长串的限制。

列表甚至更长,可能不是详尽的,因为sa2django是一个针对作者当前需求定制的年轻项目。

  • 目前只支持声明性基础定义,不支持纯Mapper对象
  • 复合外键和主键不受支持。主键和外键必须包含恰好一个列
  • 不使用外键的关系不会添加到Django模型中

多对多关系

  • 在SQLAlchemy中,在中继表的映射器中,必须指定指向两个表的外键和关系。

    示例

    class CarParentAssoc(Base):
        __tablename__ = "cartoparent"
        id = Column(Integer, primary_key=True)
        car = relationship("Car")
        parent = relationship("Parent")
        car_id = Column(Integer, ForeignKey("car.car_id"))
        parent_id = Column(Integer, ForeignKey("parent.id"))
    

    注意,对于指向carparent表的链接,都指定了外键和关系属性。

变更日志

0.2.1

  • 限制到SQLAlchemy <1.4

0.2.0

  • 从多对一关系推导出外键,而不是依赖于显式的外键列

0.1.3

  • 为没有在SQLAlchemy中定义长度的字符串字段设置任意max_length为2048。这是必要的,因为Django不支持无限制的字符串字段,尽管一些后端(例如Postgres)支持

贡献

欢迎发送拉取请求!理想情况下,通过创建或回复Github票据来联系我们,以便我们协调我们的工作和想法。

许可证

MIT

作者:Marius Helf (helfsmarius@gmail.com)

项目详情


下载文件

下载适用于您平台的应用程序。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

sa2django-0.2.1.tar.gz (10.0 kB 查看哈希值)

上传时间 源代码

构建分发

sa2django-0.2.1-py3-none-any.whl (9.0 kB 查看哈希值)

上传时间 Python 3

由以下支持