我第一次与SQLAlchemy和Flask一起创建API,并且尝试使用Entity Framework在.NET中做很多次我以前做过的事情,这是为我的CRUD操作创建一个模型,合并视图和表格中的列。我想知道是否有可能做,或者我想做的不是在Flask / SQLAlchemy中做到这一点的“正确”方法。我也在使用flask-sqlalchemy库。

这是两个模型:

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)


Pigeon映射到表,PigeonView映射到视图(数据库是mySQL)。

这是视图:

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和该鸽子被踢了多少次的整数。

(还有另一个名为“踢事件”的模型/表,该信息/来自此看起来像这样)

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)


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

像这样:

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中,我将执行以下操作将这些属性映射到我的最终目标Pigeon类:

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到达那里,因为整个过程显然与Entity Framework完全不同。

最佳答案

经过进一步的挖掘,我决定完全删除视图,将Pigeons附加到具有关系的KickEvents上,并添加column属性以求和。

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,这不是我的原始代码中的列)

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

从这里获取所有这些信息:https://docs.sqlalchemy.org/en/13/orm/mapped_sql_expr.html

希望这对任何研究同一问题的人有所帮助。另外,如果我完全以错误的方式进行操作,请告诉我。我很想知道是否有更好的方法。

10-07 17:48