Should ModelField.choices accept a callable?

153 views
Skip to first unread message

Josh Smeaton

unread,
Jan 11, 2018, 7:55:50 PM1/11/18
to Django developers (Contributions to Django itself)
https://code.djangoproject.com/ticket/22837 was closed as invalid. It concerns itself with migrations being detected when model field choices (which may be dynamic) change. The workaround suggested is to pass a callable to choices with a link to https://code.djangoproject.com/ticket/13181. However, that ticket only concerns itself with FormField.choices accepting a callable.

There are many times where dynamic choices causes unnecessary migrations to be detected, sometimes in external apps:

- pytz gains new timezone codes
- country codes are added or removed
- new states are added to an internal library
- settings determine the set of choices

I would like to reconsider reopening https://code.djangoproject.com/ticket/22837 with the goal of making ModelField.choices accept a callable. There is sufficient frustration within the community to warrant such a change I feel.

Tim Graham

unread,
Jan 11, 2018, 9:32:20 PM1/11/18
to Django developers (Contributions to Django itself)
Is "accept a callable" the best solution for everywhere this problem occurs? For example, same thing was proposed in "FileField storage param should allow a callable" (#28184). It seems a bit odd to me that on the one hand we say that we need to track changes to all model field attributes, but then we avoid that by hiding changes behind a callable.

https://code.djangoproject.com/ticket/28184

Josh Smeaton

unread,
Jan 11, 2018, 9:50:34 PM1/11/18
to Django developers (Contributions to Django itself)
Migrations are mainly for tracking database changes. Model attributes not SQL related are pushed into the migrations also, presumably for the purposes of data migrations (maybe post-hoc justification, only a few people would actually know). Providing a callable still provides access to the data as defined as migration time. But for dynamic content like choices, the set of production values can and will differ from the set of dev values. 

Perhaps there should be a more general mechanism for opting specific kwargs out of migrations - I don't know.

Adam Johnson

unread,
Jan 12, 2018, 12:42:12 PM1/12/18
to django-d...@googlegroups.com
I'd be more in favour of opting specific kwargs out of migrations, it keeps the interface simpler for users. There's a barrier to understanding Field(choices=func_that_returns_a_plain_list).

As an note, Django-MySQL's EnumField uses the values in choices at the database layer to define an ENUM type column: https://django-mysql.readthedocs.io/en/latest/model_fields/enum_field.html , so it would need to opt back in choices affecting migrations, if Django went the route of ignoring it.

On 12 January 2018 at 02:50, Josh Smeaton <josh.s...@gmail.com> wrote:
Migrations are mainly for tracking database changes. Model attributes not SQL related are pushed into the migrations also, presumably for the purposes of data migrations (maybe post-hoc justification, only a few people would actually know). Providing a callable still provides access to the data as defined as migration time. But for dynamic content like choices, the set of production values can and will differ from the set of dev values. 

Perhaps there should be a more general mechanism for opting specific kwargs out of migrations - I don't know.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscribe@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/382314ae-b3e4-4ce6-be34-135060978317%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Adam

Israel Fermin Montilla

unread,
Jan 13, 2018, 1:30:06 PM1/13/18
to Django developers (Contributions to Django itself)
Most of the cases where I wanted (or needed) dynamic choices, I've solved them by using a normal CharField() on the model and a ChoiceField() in the form and enforce the choices there.

Models are persistence layer and the changes here, in my opinion as a first time poster in the group, should be tracked through migrations. However, I think the option of not doing so under your own responsibility should be there. On one hand, you need to enforce a certain range of values from the database most of the time and on the other hand, in some cases you need the flexibility to add or remove dynamically without sending DDL to the database.
Reply all
Reply to author
Forward
0 new messages