Как сопоставить представление и таблицу с одной моделью, используя SQLAlchemy? - PullRequest
1 голос
/ 02 февраля 2020

Я впервые работаю с SQLAlchemy и Flask, чтобы создать API, и пытаюсь сделать то, что я делал много раз в. NET, используя Entity Framework, который предназначен для создания одна модель для моих операций 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 сопоставлен с представлением (DB является 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

По сути, это просто идентификатор голубя и целое число раз, сколько голубя пнули.

(Существует еще одна модель / таблица, называемая «События пика», откуда поступает эта информация, которая выглядит следующим образом)

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, а также столбец kick_events из представления Pigeon. (И, возможно, любые другие переменные, которые добавляются в представление голубя).

Примерно так:

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

In. 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.

1 Ответ

0 голосов
/ 02 февраля 2020

После дальнейших раскопок я решил полностью очистить представление, присоединить голубей к KickEvents со связью и добавить свойство столбца для суммирования ударов.

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

Надеюсь, это поможет любому разобраться в той же проблеме. Также, если я ошибся в этом, пожалуйста, скажите мне. Я хотел бы знать, есть ли лучший способ.

...