f3-data-models 0.3.6__py3-none-any.whl → 0.3.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ from f3_data_models.models import Event, Day_Of_Week, Event_Cadence, EventType_x_Event
2
+ import datetime
3
+ from f3_data_models.utils import DbManager
4
+
5
+
6
+ def test_update_event():
7
+ event = Event(
8
+ org_id=3,
9
+ location_id=2,
10
+ is_series=True,
11
+ is_active=True,
12
+ highlight=True,
13
+ start_date=datetime.date(2025, 2, 17),
14
+ end_date=datetime.date(2026, 2, 17),
15
+ start_time="0500",
16
+ end_time="0600",
17
+ event_x_event_types=[
18
+ EventType_x_Event(event_type_id=4),
19
+ ],
20
+ recurrence_pattern=Event_Cadence.weekly,
21
+ day_of_week=Day_Of_Week.monday,
22
+ recurrence_interval=1,
23
+ index_within_interval=1,
24
+ name="Test Event",
25
+ )
26
+ update_dict = event.__dict__
27
+ DbManager.update_records(Event, [Event.id == 3], update_dict)
28
+
29
+ # with get_session() as session:
30
+ # # delete event_x_event_types
31
+ # session.query(EventType_x_Event).filter(
32
+ # EventType_x_Event.event_id == 3
33
+ # ).delete()
34
+ # # add event_x_event_types
35
+ # session.add(EventType_x_Event(event_id=3, event_type_id=4))
36
+ # session.commit()
37
+
38
+
39
+ if __name__ == "__main__":
40
+ test_update_event()
f3_data_models/utils.py CHANGED
@@ -9,7 +9,6 @@ from sqlalchemy.dialects.postgresql import insert
9
9
  from sqlalchemy.engine import Engine
10
10
  from sqlalchemy.orm import sessionmaker, joinedload
11
11
  from sqlalchemy.orm.collections import InstrumentedList
12
- from sqlalchemy.orm.attributes import flag_modified
13
12
 
14
13
  from f3_data_models.models import Base
15
14
 
@@ -17,6 +16,8 @@ from pydot import Dot
17
16
  from sqlalchemy_schemadisplay import create_schema_graph
18
17
  from google.cloud.sql.connector import Connector, IPTypes
19
18
  import pg8000
19
+ from sqlalchemy.orm import class_mapper
20
+ from sqlalchemy.orm.attributes import InstrumentedAttribute
20
21
 
21
22
 
22
23
  @dataclass
@@ -167,33 +168,57 @@ class DbManager:
167
168
  close_session(session)
168
169
 
169
170
  def update_record(cls: T, id, fields):
170
- session = get_session()
171
- # Fetch the object to be updated
172
- obj = session.query(cls).get(id)
173
- if not obj:
174
- raise ValueError(f"Object with id {id} not found")
175
-
176
- # Get the list of valid attributes for the class
177
- valid_attributes = {attr.key for attr in inspect(cls).mapper.column_attrs}
178
- valid_relationships = {rel.key for rel in inspect(cls).mapper.relationships}
179
-
180
- # Update simple fields
181
- for key, value in fields.items():
182
- if key in valid_attributes and not isinstance(value, InstrumentedList):
183
- setattr(obj, key, value)
184
-
185
- # Update relationships
186
- for key, value in fields.items():
187
- if key in valid_relationships and isinstance(value, InstrumentedList):
188
- related_objects = getattr(obj, key)
189
- related_objects.clear()
190
- related_objects.extend(value)
191
-
192
- # Flag the object as modified to ensure changes are detected
193
- flag_modified(obj, key)
194
-
195
- # Commit the changes
196
- session.commit()
171
+ with get_session() as session:
172
+ record = session.query(cls).get(id)
173
+ if not record:
174
+ raise ValueError(f"Record with id {id} not found in {cls.__name__}")
175
+
176
+ mapper = class_mapper(cls)
177
+ relationships = mapper.relationships.keys()
178
+ for key, value in fields.items():
179
+ if hasattr(cls, key) and key not in relationships:
180
+ attr = getattr(cls, key)
181
+ if isinstance(attr, InstrumentedAttribute):
182
+ setattr(record, key, value)
183
+ elif key in relationships:
184
+ # Handle relationships separately
185
+ relationship = mapper.relationships[key]
186
+ related_class = relationship.mapper.class_
187
+ # find mapping of related_class
188
+ og_primary_key = None
189
+ for k in related_class.__table__.foreign_keys:
190
+ if k.references(cls.__table__):
191
+ og_primary_key = k.constraint.columns[0].name
192
+ break
193
+
194
+ if isinstance(value, list) and og_primary_key:
195
+ # Delete existing related records
196
+ related_class = relationship.mapper.class_
197
+ related_relationships = class_mapper(
198
+ related_class
199
+ ).relationships.keys()
200
+ session.query(related_class).filter(
201
+ getattr(related_class, og_primary_key) == id
202
+ ).delete()
203
+ # Add new related records
204
+ items = [item.__dict__ for item in value]
205
+ for related_item in items:
206
+ update_dict = {
207
+ k: v
208
+ for k, v in related_item.items()
209
+ if hasattr(related_class, k)
210
+ and k not in related_relationships
211
+ }
212
+ related_record = related_class(
213
+ **{og_primary_key: id, **update_dict}
214
+ )
215
+ session.add(related_record)
216
+
217
+ try:
218
+ session.commit()
219
+ except pg8000.IntegrityError as e:
220
+ session.rollback()
221
+ raise e
197
222
 
198
223
  def update_records(cls, filters, fields):
199
224
  session = get_session()
@@ -213,15 +238,41 @@ class DbManager:
213
238
  ):
214
239
  setattr(obj, key, value)
215
240
 
216
- # Update relationships
241
+ # Update relationships separately
217
242
  for key, value in fields.items():
218
- if key in valid_relationships and isinstance(
219
- value, InstrumentedList
220
- ):
221
- related_objects = getattr(obj, key)
222
- related_objects.clear()
223
- related_objects.extend(value)
224
- flag_modified(obj, key)
243
+ if key in valid_relationships:
244
+ # Handle relationships separately
245
+ relationship = inspect(cls).mapper.relationships[key]
246
+ related_class = relationship.mapper.class_
247
+ # find mapping of related_class
248
+ og_primary_key = None
249
+ for k in related_class.__table__.foreign_keys:
250
+ if k.references(cls.__table__):
251
+ og_primary_key = k.constraint.columns[0].name
252
+ break
253
+
254
+ if isinstance(value, list) and og_primary_key:
255
+ # Delete existing related records
256
+ related_class = relationship.mapper.class_
257
+ related_relationships = class_mapper(
258
+ related_class
259
+ ).relationships.keys()
260
+ session.query(related_class).filter(
261
+ getattr(related_class, og_primary_key) == obj.id
262
+ ).delete()
263
+ # Add new related records
264
+ items = [item.__dict__ for item in value]
265
+ for related_item in items:
266
+ update_dict = {
267
+ k: v
268
+ for k, v in related_item.items()
269
+ if hasattr(related_class, k)
270
+ and k not in related_relationships
271
+ }
272
+ related_record = related_class(
273
+ **{og_primary_key: obj.id, **update_dict}
274
+ )
275
+ session.add(related_record)
225
276
 
226
277
  session.flush()
227
278
  finally:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: f3-data-models
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: The data schema and models for F3 Nation applications.
5
5
  License: MIT
6
6
  Author: Evan Petzoldt
@@ -0,0 +1,7 @@
1
+ f3_data_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ f3_data_models/models.py,sha256=SLOXwM2BMnlGTwkVZfG3fM9hoksvPkcFRqzpEI4bm2Y,44293
3
+ f3_data_models/testing.py,sha256=vetCEBQC8R1hf0TcH3-lINXdlHMVIcjC6OhVWiiFWU0,1204
4
+ f3_data_models/utils.py,sha256=5Hg0f1cPMYc-URdTbDTLMiG9rCFN5NskJ4lUHw1a2NU,13747
5
+ f3_data_models-0.3.7.dist-info/METADATA,sha256=F34OA9YQW-60PwJ77YytFIHNL_-zMlbew6t23Rrdfm4,2716
6
+ f3_data_models-0.3.7.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
7
+ f3_data_models-0.3.7.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- f3_data_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- f3_data_models/models.py,sha256=SLOXwM2BMnlGTwkVZfG3fM9hoksvPkcFRqzpEI4bm2Y,44293
3
- f3_data_models/utils.py,sha256=fGv-qHviSsUqHmYElBvYgWbqX5LAlTJCoKSMIqd8ioA,10738
4
- f3_data_models-0.3.6.dist-info/METADATA,sha256=G6dtENVh5a3JKZ4NdCl3DVY6dTybhdEl5jLvQmKnFHY,2716
5
- f3_data_models-0.3.6.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
6
- f3_data_models-0.3.6.dist-info/RECORD,,