问题
I am inserting a list of python dictionaries into a Postgres database using SQL Alchemy (via Flask_sqlalchemy).
One of the tables is a list of all unique items (table 1), while the second is a time series of data related to an item (table2).
In essence, I want to insert any new row (with unique hash) in to table 1, then insert it's data to table 2. If it already exists in table 1, just insert the "child" in table 2 referencing the entry in table 1.
This is one item in the list, the list has a few hundred of these.
{'placement': '5662448s608653114', 't1': datetime.datetime(2018, 4, 15, 17, 47, 7, 434982), 't2': datetime.datetime(2018, 4, 25, 17, 47, 7, 434994), 'camp_id': 1, 'clicks': '0', 'visits': '3', 'conversions': '0', 'revenue': '0'}
I would like to insert 5662448s608653114 into table1, and then insert all the other data into table2, where i reference the item not by 5662448s608653114, but by it's id in table 1
So I'd get:
Table 1:
____________________
1| 5662448s608653114
2| 5520103
Table 2:
ID | Pl id | T1 | T2 | cost | revenue | clicks
_______________________________________________
499| 1 |
500| 2 |
I tested this, which does not work:
def write_tracker_data(self):
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
pl = TrackerPlacementData(placement_id=ts.id, t1=item["t1"], t2=item["t2"], camp_id=1, revenue=item["revenue"], clicks=item["clicks"], conversions=item["conversions"])
db.session.add(pl)
db.session.commit()
The above code inserts the data, but with none instead of the id from the Table 1. It also doesn't seem very efficient, you know that feeling when something can definitely be done a better way ...
Here's the model classes for reference:
class Placements(db.Model):
id = db.Column(db.Integer, primary_key=True)
traffic_source = db.Column(db.Integer, db.ForeignKey('ts_types.id'))
placement_ts_hash = db.Column(db.String, index=True)
placement_url = db.Column(db.String)
placement_type = db.Column(db.String)
# Relationship betwwen unique placement table and tracker_placeemnt_data
tracker_data = db.relationship("TrackerPlacementData", backref="placement_hash")
class TrackerPlacementData(db.Model):
id = db.Column(db.Integer, primary_key=True)
t1 = db.Column(db.DateTime(timezone=True))
t2 = db.Column(db.DateTime(timezone=True), index=True)
camp_id = db.Column(db.Integer, db.ForeignKey('campaigns.id'), nullable=False)
placement_id = db.Column(db.Integer, db.ForeignKey('placements.id'), nullable=True, index=True)
revenue = db.Column(db.Float)
clicks = db.Column(db.Integer)
conversions = db.Column(db.Integer)
Thanks in advance.
Edit: This works, but it doesn't seem very good due to a new session for every item in the loop :/
def write_tracker_data(self):
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
db.session.add(ts)
db.session.commit()
pl = TrackerPlacementData(placement_hash=ts, t1=item["t1"], t2=item["t2"], camp_id=1,
revenue=item["revenue"], clicks=item["clicks"], conversions=item["conversions"])
db.session.add(pl)
db.session.commit()
回答1:
Your Placement
instance won't have an id until it is committed. This is where the tracker_data
relationship can help you...
for item in self.data:
ts = Placements(placement_ts_hash=item["placement"])
pl = TrackerPlacementData(
t1=item["t1"],
t2=item["t2"],
camp_id=1,
revenue=item["revenue"],
clicks=item["clicks"],
conversions=item["conversions"]
)
ts.tracker_data.append(pl)
db.session.add(ts)
db.session.commit()
Notice that pl.placement_id
is not set to anything. Instead pl
is appended to ts.tracker_data
and everything should be looked after for you when you call commit.
来源:https://stackoverflow.com/questions/50026672/sql-alchemy-how-to-insert-data-into-two-tables-and-reference-foreign-key