Repository navigation
feat: foreign keys in primary keys, to_field and db_constraint (relation keys, phase 3a) - #1927
Conversation
…ro keys, release notes)
…se-2 # Conflicts: # ormar/models/descriptors/descriptors.py # tests/test_model_definition/test_primary_key.py
…N, persisted state)
…rgets, serialization)
…phase-2 # Conflicts: # docs/releases.md # ormar/fields/foreign_key.py # ormar/fields/many_to_many.py # ormar/models/descriptors/descriptors.py # ormar/models/helpers/sqlalchemy.py # ormar/models/mixins/save_mixin.py # ormar/models/model.py # ormar/models/newbasemodel.py # ormar/models/primary_key.py # ormar/queryset/clause.py # ormar/queryset/queryset.py # ormar/queryset/templates/writes.py # tests/test_model_definition/test_primary_key.py
Model.pk on a composite key is now a key accessor: == and in_() / << compile to the same row-value comparison as pk= / pk__in=, and asc() / desc() order by every key field. .pk also works after relations (Book.author.pk == 1) for single and composite keys.
Ordering by pk only worked in order_by() on the queried model. pk after
relations (order_by("stock__pk"), Shop.stock.pk.desc()), ormar_config
order_by=["-pk"] and relation orders_by / related_orders_by produced
invalid SQL, for single keys too. A shared order_actions_for() helper now
expands pk into the key fields of the model the chain points at, and is
used by QuerySet.order_by, model default ordering and join orderings.
…phase-3a # Conflicts: # docs/models/primary-keys.md # docs/releases.md # ormar/fields/foreign_key.py # ormar/models/model.py # ormar/models/newbasemodel.py # ormar/models/primary_key.py # ormar/queryset/clause.py # tests/test_model_definition/test_composite_pk_definition.py
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Merging this PR will degrade performance by 6.48%3 warnings, 1 note
Performance Changes
Tip Curious why performance improved? Comment Comparing |
Detached copies dropped their relations, so a required foreign key (one in the primary key) read None and the validated rebuild failed. Register bare copies of the forward relations instead and run the reverse select_related test with the cross-check on.
Part of #137.
ForeignKey(..., primary_key=True)lets a foreign key be (part of) the primary key — link tables keyed by their foreign keys and shared primary keys — with key values holding the referenced values (enrollment.pk == (student.id, course.id)).ForeignKey(..., to_field="iso_code")references a unique non-pk column, anddb_constraint=Falseskips the databaseFOREIGN KEY. Relations to models keyed by a foreign key, bulk writes,QuerySet.update, flattened pydantic models and key-only models all use the referenced value; pk ordering andModel.pkfilters from phase 2 work on these keys too. Multi-column foreign keys follow in phase 3b.enrollment.pk = (...)) updates the relation itself.Model.load()of a model without a key raisesNoMatchwithout querying.tests/cross_check.pysafety net now keeps forward relations on its detached copies, so reverseselect_relatedinto models keyed by a foreign key is cross-checked too instead of being switched off.