首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用SQLAlchemy将视图和表映射到一个模型?

如何使用SQLAlchemy将视图和表映射到一个模型?
EN

Stack Overflow用户
提问于 2020-02-02 08:41:25
回答 1查看 572关注 0票数 1

我第一次使用SQLAlchemy和Flask创建一个应用程序接口,我正在尝试做一些我以前使用实体框架在.NET中做过很多次的事情,那就是为我的CRUD操作创建一个模型,它组合了视图和表中的列。我想知道是否有可能这样做,或者我尝试做的事情是否不是在Flask/SQLAlchemy中做这件事的“正确”方法。我还使用了flask-sqlalchemy库。

这里有两个模型:

代码语言:javascript
运行
复制
class PigeonView(db.Model):
    __table_args__ = {'info': dict(is_view=True)}
    id = db.Column(db.Integer, db.ForeignKey('pigeon.id')
    kick_events = db.Column(db.Integer)

class PigeonBase(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(255), nullable=False)
    date_created = db.Column(db.DateTime, nullable=False)

mySQL映射到一个表,PigeonView映射到一个视图( DB是Pigeon )。

这是视图:

代码语言:javascript
运行
复制
CREATE VIEW pigeon_view AS 
    SELECT 
        p.id AS id, 
        COALESCE(SUM(k.pigeon_id), 0) AS kick_events 
    FROM pigeon p 
    LEFT JOIN kick_event k 
    ON p.Id = k.pigeon_id GROUP BY p.Id

基本上,只有一个鸽子ID和一个整数,表示鸽子被踢了多少次。

(还有另一个名为Kick Events的模型/表,该信息来自于该模型/表,如下所示)

代码语言:javascript
运行
复制
class KickEvent(db.Model):
    __tablename__ = "kick_event"

    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    pigeon_id = db.Column(db.Integer, db.ForeignKey('pigeon.id'), primary_key=True)
    date = db.Column(db.DateTime)

作为最终结果,我想要的是一个鸽子模型,它包含了鸽子表中的所有内容以及鸽子视图中的kick_events列。(可能还有添加到鸽子视图中的任何其他变量)。

如下所示:

代码语言:javascript
运行
复制
class Pigeon(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True) #from pigeon table
    name = db.Column(db.String(255), nullable=False) #from pigeon table
    date_created = db.Column(db.DateTime, nullable=False) #from pigeon table
    kick_events = db.Column(db.Integer) #from pigeon view

在.NET / Entity Framework中,我会这样做,将这些属性映射到我的最终目标鸽类:

代码语言:javascript
运行
复制
this.HasKey((x => x.Id));

this.Property(x => x.Name).HasColumnName("Name");
this.Property(x => x.DateCreated).HasColumnName("DateCreated");
this.Property(x => x.KickEvents).HasColumnName("KickEvents");

Map(m =>
{
    m.Properties(p => new
    {
        p.Id,
        p.Name,
        p.DateCreated
    });
    m.ToTable("Pigeon");
});

Map(m =>
{
    m.Properties(p => new
    {
        p.Id,
        p.KickEvents
    });
    m.ToTable("PigeonView");
});

但我不确定如何使用Python/SQLAlchemy实现,因为整个过程显然与实体框架非常不同。

EN

回答 1

Stack Overflow用户

发布于 2020-02-02 13:25:42

在进一步研究之后,我决定完全取消视图,使用关系将鸽子附加到KickEvents,并添加一个列属性来计算总和。

代码语言:javascript
运行
复制
class Pigeon(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(255), nullable=False)
    date_created = db.Column(db.DateTime, nullable=False)
    kick_events = db.Column(db.Integer)
    kick_events = relationship("KickEvent"),
    kick_count = column_property(
        select([func.count(KickEvent.id)]).\
            where(KickEvent.pigeon_id==id).\
            correlate_except(KickEvent))

(与解决方案不太相关,但我还修改了KickEvents,使其具有一个用作主键的Id,因为我决定希望用户能够多次踢同一只鸽子,这就是为什么我能够计算KickEvent.Id,它不是我原始代码中的一个列)

我猜这并没有真正回答我提出的问题,因为我没有组合一个表和一个视图,但在完全摆脱视图之后,我仍然得到了我想要的最终结果,那就是一个包含鸽子表和一个基于与鸽子(KickEvent)关系的表计算的值的单一模型。

我从这里学到了所有这些:https://docs.sqlalchemy.org/en/13/orm/mapped_sql_expr.html

我希望这对任何研究同样问题的人都有所帮助。另外,如果我完全走错了路,请告诉我。我很想知道有没有更好的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60022360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档