Entities
Aggregates cluster multiple domain elements together to represent a concept. They are usually composed of two kinds of elements - those with unique identities (Entities) and those without (Value Objects).
Entities represent unique objects in the domain model just like Aggregates, but they don’t manage other objects. Just like Aggregates, Entities are identified by unique identities that remain the same throughout its life - they are not defined by their attributes or values. For example, a passenger in the airline domain is an Entity. The passenger’s identity remains the same across multiple seat bookings, even if her profile information (name, address, etc.) changes over time.
Note
In Protean, Aggregates are actually entities that have taken on the additional responsibility of managing the lifecycle of one or more related entities.
Definition
An Entity is defined with the Domain.entity
decorator:
from protean.domain import Domain
from protean.fields import Date, String
publishing = Domain(__name__)
@publishing.aggregate
class Post:
name = String(max_length=50)
created_on = Date()
@publishing.entity(part_of=Post)
class Comment:
content = String(max_length=500)
An Entity has to be associated with an Aggregate. If part_of
is not
specified while defining the identity, you will see an IncorrectUsageError
:
>>> @publishing.entity
... class Comment:
... content = String(max_length=500)
...
IncorrectUsageError: 'Entity `Comment` needs to be associated with an Aggregate'
An Entity cannot enclose another Entity (or Aggregate). Trying to do so will
throw IncorrectUsageError
.
>>> @publishing.entity
... class SubComment:
... parent = Comment()
...
IncorrectUsageError: 'Entity `Comment` needs to be associated with an Aggregate'
Configuration
Similar to an aggregate, an entity's behavior can be customized with by passing
additional options to its decorator, or with a Meta
class as we saw earlier.
Available options are:
abstract
Marks an Entity as abstract if True
. If abstract, the entity cannot be
instantiated and needs to be subclassed.
auto_add_id_field
If True
, Protean will not add an identifier field (acting as primary key)
by default to the entity. This option is usually combined with abstract
to
create entities that are meant to be subclassed by other aggregates.
schema_name
The name to store and retrieve the entity from the persistence store. By
default, schema_name
is the snake case version of the Entity's name.
model
Similar to an aggregate, Protean automatically constructs a representation of the entity that is compatible with the configured database. While the generated model suits most use cases, you can also explicitly construct a model and associate it with the entity, just like in an aggregate.
Note
An Entity is always persisted in the same persistence store as the its Aggregate.
Associations
Entities can be further enclose other entities within them, with the HasOne
and HasMany
relationships, just like in an aggregate. Refer to the Aggregate's
Association documentation for more details.