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.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top