Skip to content

Fix inconsistent .pk behaviour with custom primary keys#784

Merged
abrookins merged 1 commit intomainfrom
fix/570-inconsistent-pk-behaviour
Jan 23, 2026
Merged

Fix inconsistent .pk behaviour with custom primary keys#784
abrookins merged 1 commit intomainfrom
fix/570-inconsistent-pk-behaviour

Conversation

@abrookins
Copy link
Collaborator

Summary

Fixes #570 - When using a custom primary key field (e.g., x: int = Field(primary_key=True)), accessing .pk on an instance now correctly returns the actual value instead of an ExpressionProxy or auto-generated ULID.

Changes

  1. Added PrimaryKeyAccessor descriptor class that:

    • Returns the actual primary key value for instance-level access
    • Returns ExpressionProxy for class-level access (query building)
    • Handles setting the primary key value correctly
  2. Modified ModelMeta.__new__ to:

    • Detect when there's exactly one custom primary key (not pk)
    • Remove the default pk field from model_fields
    • Set up the PrimaryKeyAccessor descriptor for .pk access
  3. Updated validate_primary_key() to safely handle cases where pk was already removed

Example

class Member(HashModel, index=True):
    x: int = Field(primary_key=True)
    name: str

member = Member(x=42, name="Test")
print(member.pk)  # Now correctly prints: 42 (was: ExpressionProxy before fix)
print(member.x)   # Prints: 42

# Class-level access still works for queries
await Member.find(Member.pk == 42).all()

Testing

  • Added tests for both HashModel and JsonModel
  • All 226 existing tests pass

When a model uses a custom primary key field (e.g., x: int = Field(primary_key=True)),
accessing .pk now correctly returns the actual value instead of an ExpressionProxy.

Adds PrimaryKeyAccessor descriptor that redirects .pk access to the custom primary
key field value while preserving ExpressionProxy for class-level query building.

Fixes #570
@abrookins abrookins merged commit 9d9c0ce into main Jan 23, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid Pydantic validation on search query

1 participant