@@ -2552,6 +2552,14 @@ class Config:
25522552 # Set up PrimaryKeyAccessor descriptor for .pk access
25532553 setattr (new_class , "pk" , PrimaryKeyAccessor ())
25542554
2555+ # For embedded models, clear the primary_key from meta since they don't
2556+ # need primary keys - they're stored as part of their parent document,
2557+ # not as separate Redis keys. This fixes GitHub issue #496.
2558+ # Note: We keep the pk field in model_fields but the validator will
2559+ # return None and model_dump will exclude it.
2560+ if getattr (new_class ._meta , "embedded" , False ):
2561+ new_class ._meta .primary_key = None
2562+
25552563 if not getattr (new_class ._meta , "global_key_prefix" , None ):
25562564 new_class ._meta .global_key_prefix = getattr (
25572565 base_meta , "global_key_prefix" , ""
@@ -2770,6 +2778,9 @@ async def expire(
27702778
27712779 @field_validator ("pk" , mode = "after" )
27722780 def validate_pk (cls , v ):
2781+ # Skip pk generation for embedded models - they don't need primary keys
2782+ if getattr (cls ._meta , "embedded" , False ):
2783+ return None
27732784 if not v or isinstance (v , ExpressionProxy ):
27742785 v = cls ._meta .primary_key_creator_cls ().create_pk ()
27752786 return v
@@ -2778,13 +2789,24 @@ def validate_pk(cls, v):
27782789
27792790 @field_validator ("pk" )
27802791 def validate_pk (cls , v ):
2792+ # Skip pk generation for embedded models - they don't need primary keys
2793+ if getattr (cls ._meta , "embedded" , False ):
2794+ return None
27812795 if not v or isinstance (v , ExpressionProxy ):
27822796 v = cls ._meta .primary_key_creator_cls ().create_pk ()
27832797 return v
27842798
27852799 @classmethod
27862800 def validate_primary_key (cls ):
2787- """Check for a primary key. We need one (and only one)."""
2801+ """Check for a primary key. We need one (and only one).
2802+
2803+ Embedded models are exempt from this check since they don't need
2804+ primary keys - they're stored as part of their parent document.
2805+ """
2806+ # Skip validation for embedded models - they don't need primary keys
2807+ if getattr (cls ._meta , "embedded" , False ):
2808+ return
2809+
27882810 primary_keys = 0
27892811 for name , field in cls .model_fields .items ():
27902812 if (
@@ -3823,5 +3845,17 @@ def schema_for_type(
38233845
38243846
38253847class EmbeddedJsonModel (JsonModel , abc .ABC ):
3848+ """
3849+ A model intended to be embedded within a JsonModel.
3850+
3851+ EmbeddedJsonModels are stored as part of their parent document, not as
3852+ separate Redis keys, so they do not need or generate primary keys.
3853+
3854+ The pk field is excluded from serialization by default.
3855+ """
3856+
3857+ # Override pk to exclude it from serialization - embedded models don't need pks
3858+ pk : Optional [str ] = Field (default = None , exclude = True )
3859+
38263860 class Meta :
38273861 embedded = True
0 commit comments