Запрос Flask-SQLAlchemy через два объединения таблиц - соединение не работает - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь объединить два стола.

Вот упрощенные таблицы

class Spots(db.Model):
    __tablename__ = "spots"

    geobaseid = db.Column((db.Integer), primary_key=True,autoincrement=True)
    spot = db.Column(db.String(50))
    url_slug = db.Column(db.String(50))
    region = db.Column(db.String(50))
    country = db.Column(db.String(50))
    chop = db.Column(db.Integer)
    small_wave = db.Column(db.Integer)
    flat = db.Column(db.Integer)
    big_wave = db.Column(db.Integer)
    west_direction = db.Column(db.Integer)
    southwest_direction = db.Column(db.Integer)
    amount = db.Column(db.Integer)
    url_slug = db.Column(db.String(50))

    forcast = db.relationship('Forcast_short')

class Forcast_short(db.Model):
    __tablename__ = "forcast_short"

    id = db.Column((db.Integer), primary_key=True,autoincrement=True)
    date = db.Column(db.Date)
    geobaseid = db.Column((db.Integer), ForeignKey('spots.geobaseid'))
    spot = db.Column(db.String(50))
    region = db.Column(db.String(50))
    country = db.Column(db.String(50))
    latitude = db.Column(db.Numeric(10,8))
    longitude = db.Column(db.Numeric(10,8))
    deg = db.Column(db.Numeric(65,1))
    mps = db.Column(db.Numeric(65,1))

Вот мой запрос, который не работает

forcast_query = Forcast_short.query.join(Spots, Spots.geobaseid==Forcast_short.geobaseid).filter(Forcast_short.region == region).all()

Что я делаю не так?

Когда явыполнить запрос, я получаю только результаты из Forcast_short с и без фильтра.

<tbody>
                  <tr>{%for row in forcast_query%}
                    <td><a href="/spots/{{row.url_slug}}"> {{row.spot}} </a></td>
                    <td>{{row.mps}} </td>
                    <td>{{row.url_slug}} </td>

                  </tr>
                  {%endfor%}
                </tbody>

Этот запрос работает в Mysql Workbench.

select * from
(
SELECT * FROM sc_db2.forcast_short

) a
 join 
(
select * from sc_db2.spots
) b
on a.geobaseid = b.geobaseid

;

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Вот более короткий пример, который иллюстрирует отношение «один ко многим» между точками и прогнозами (я думаю, это то, что вы пытаетесь сделать):

from app import db

class Spot(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    geobaseid = db.Column(db.Integer)
    forecasts = db.relationship('Forecast', backref='spot', lazy='dynamic')


class Forecast(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    region = db.Column(db.String(50))
    spot_id = db.Column(db.Integer, db.ForeignKey('spot.id'))

Объект db установленв инициализаторе пакета app, следуя шаблону Мигеля Гринберга :

from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

from app import models

Обратите внимание, что после установки отношения с внешним ключом вам не нужно явное соединение для доступа кродительские поля из дочернего объекта - SQLAlchemy позволяет просто использовать точечную запись:

>>> from app import db
>>> from app.models import Spot, Forecast
>>> for spot in Spot.query.all():
...     print(spot.id, spot.geobaseid)
...
1 1
2 2
>>> for forecast in Forecast.query.all():
...     print(forecast.id, forecast.region, forecast.spot_id, forecast.spot.geobaseid)
...
1 Scotland 2 2
2 England 2 2
0 голосов
/ 03 октября 2019

То, как вы сделали свои модели, довольно запутанно. В соответствии с документацией sqlalchemy на Patterns Patterns , которую я советую прочитать, вот как вы должны установить отношения один ко многим:

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

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

Это отношение помещает внешний ключ в дочернюю таблицу, ссылающуюся на родительский. Затем в родительском элементе указывается relationship() как ссылка на коллекцию предметов, представленных дочерним элементом.

О ВАШЕМ ЗАПРОСЕ:

После согласования ваших моделей ваш запросдолжно выглядеть так:

forcast_query = Forcast_short.query.join(Spots, Spots.geobaseid==Forcast_short.geobaseid).filter(Forcast_short.region == region).filter(Forcast_short.date == date_1).all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...