Consider grouping the constants exported by `django.db.models` under enums
- Dominant language
- No language data
- Stars
- 188
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
### Code of Conduct
- [x] I agree to follow Django's Code of Conduct
### Feature Description
Group the constants exported by `django.db.models` under enums, so that each set of accepted values for a given argument lives in one named place instead of the flat module namespace.
(We discussed the following idea during a Steering Council - Fellow monthly meeting, and after I created [a ticket for it](https://code.djangoproject.com/ticket/37247), the Fellows agreed that using this board first would be more appropriate, to ensure there is enough community support for the proposal before accepting it.)
### Problem
The constants exported by `django.db.models` give no hint of where they apply. Names like `SET`, 1 SET_NULL`, or `DO_NOTHING` say what happens but not which argument accepts them, and unrelated groups sit next to each other in one namespace with nothing separating them. Reading code means knowing the convention already, and writing it means guessing or checking the docs.
The problem grows with every group added. https://github.com/django/django/pull/21696 renames one constant to keep a new group from being confused with an existing one, which works but relies on prefixes holding up as more values arrive.
### Request or proposal
proposal
### Additional Details
Enums address this directly. The valid options for an argument become discoverable from a single object, membership is visible at the call site, and new groups cost nothing in namespace clarity. Django already applies the pattern inside the ORM with `Deferrable`, `WindowFrameExclusion`, the `Choices` classes and the internal `OnConflict`.
An enum was proposed during the review linked above. The Steering Council discussed it on 2026-08-03 and agreed the change makes sense across the exported constants rather than for one group in isolation, which is what this request covers.
Points that need working out:
- The constants do not share a shape. Some are plain functions, some are class instances, and `SET` is a factory returning a configured callable. Plain functions assigned in an enum body become methods rather than members, so member values need a deliberate form. One option is to give every value the same shape, a small strategy instance, which is already how the fetch modes are built (thanks @jacobtylerwalls for that pointer).
- `SET` takes an argument, so it cannot be a fixed member. It may fit as a staticmethod on the enum returning an object that implements the same protocol.
- `on_delete` accepts user supplied callables, so an enum documents the built-in options rather than closing the set of accepted values.
- Existing migration files reference the current import paths, so the module-level names have to keep resolving. `enum.Enum` is registered to `EnumSerializer`, and the autodetector deconstructs objects exposing `deconstruct()`, so newly written migrations are covered.
- Naming, and whether the current names become permanent aliases or get a deprecation path.
### Implementation Suggestions
_No response_
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the constants exported by django.db.models and compare them with Django's existing Deferrable, WindowFrameExclusion, Choices, and internal OnConflict patterns. Work through member values, the SET factory, user-supplied on_delete callables, migration compatibility, and naming or deprecation; done means the proposal has a settled design for grouping all exported constants.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- backend, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100