Fix: Populate FK columns for SQLModel/SQLAlchemy relationships - #728
Fix: Populate FK columns for SQLModel/SQLAlchemy relationships#728sachin-gracious wants to merge 5 commits into
Conversation
Fixes validation errors when creating/editing records with required foreign key relationships by using SQLAlchemy introspection to automatically populate FK columns. Problem: - _arrange_data loaded relationship objects but didn't populate FK columns - Pydantic validation failed with 'Field required' error - Only affected MANYTOONE (HasOne) relationships with required FKs Solution: - Use SQLAlchemy's inspect() and synchronize_pairs to discover FK columns - Works with ANY FK naming (user_id, owner_id, created_by, etc.) - Works with ANY PK naming (id, uuid, etc.) - Handles composite keys, None relationships, self-referential FKs - Does NOT affect ONETOMANY or MANYTOMANY relationships Changes: - Modified: starlette_admin/contrib/sqla/view.py (_arrange_data method) - Added: tests/sqla/test_sqlmodel_custom_fk.py (custom FK naming tests) - Added: tests/sqla/test_sqlmodel_manytomany.py (association table tests) - All 94 tests pass (87 existing + 7 new) Fixes: jowilf#485, jowilf#687
26fb98f to
b4102f5
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #728 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 86 88 +2
Lines 6848 7024 +176
==========================================
+ Hits 6848 7024 +176 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…fix/sqlmodel-fk-validation
jowilf
left a comment
There was a problem hiding this comment.
how is this setting the foreign columns?
- Remove '# pragma: no cover' from else branch - Add test_nonexistent_relationship_id to cover the case where find_by_pk returns None for a non-existent relationship ID - Add Project model and fixture to support the new test
Consider this model: class Employee(SQLModel, table=True):
id: Optional[int] = Field(None, primary_key=True)
name: str
dept_id: int = Field(foreign_key="dept.id") # required, custom name
department: Optional[Department] = Relationship()Step 1 — Admin excludes FK columns from its fields list
if not column.foreign_keys:
converted_fields.append(converted_field)Running against the real This is intentional — the FK column is excluded so users are not shown a raw integer input when the relationship field already handles the association. Step 2 — The form submits Without the fix, tracing the actual Step 3 — Where validation fails
self.model.validate(
{k: v for k, v in data.items() if k not in fields_to_exclude}
)
Pydantic validates this dict against the full model class definition. The critical point: Step 4 — What the fix does After for remote_col, local_col in rel_prop.synchronize_pairs:
pk_value = getattr(related_obj, remote_col.name)
arranged_data[local_col.name] = pk_value
Tracing the actual The value written is read directly from the already-loaded related object. The actual persistence of the FK column still happens through SQLAlchemy's normal relationship synchronization during Using Note on the The else branch handles the case where The FK is set to I have added |
|
is this generated by AI ? |
Fixes validation errors when creating/editing records with required foreign key relationships by using SQLAlchemy introspection to automatically populate FK columns.
Problem:
Solution:
Changes:
Fixes: #485, #687