Opened 2 months ago
Last modified 3 weeks ago
#35731 closed Cleanup/optimization
Fields with db_default, and without default, are initialized to instance of DatabaseDefault — at Initial Version
Reported by: | Kyle Bebak | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Kyle Bebak, Simon Charette, Lily Foote | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
For example, if client code creates a model Foo
with val = IntegerField(db_default=10)
, does foo = Foo()
, and accesses foo.val
, they get an instance of django.db.models.expressions.DatabaseDefault
.
This DatabaseDefault
seems to be used for bookkeeping until the model instance is written to the DB, after which foo.val
is an int
. IMO this is not a good design, because it's a case of an implementation detail (setting a value for the field once it's saved to the DB) changing the model's public interface (IMO a model instance's field values are part of its public interface).
If instead we do val = IntegerField()
, and foo = Foo()
, and access foo.val
, we get None
, s.t. the type of foo.val
is int | None
. Using db_default
means that the type of foo.val
is now int | DatabaseDefault
. DatabaseDefault
is a bookkeeping type that client code usually shouldn't interact with. If users aren't aware of db_default
's implementation, they might still write code like this, which would be broken: if foo.val is not None: print(foo.val + 10)
.
Because DatabaseDefault
is for bookkeeping, it seems like there's no reason the model instance couldn't store its DatabaseDefault
instances on a "private" field which wouldn't affect the model's public interface. This would be a lot cleaner IMO. Most users shouldn't know about DatabaseDefault
, which unsurprisingly isn't mentioned here, https://docs.djangoproject.com/en/5.1/ref/models/fields/#db-default, or anywhere else in the docs AFAICT.