I like this!

Having read through the existing ticket and discussion, really the only
reason given is a cultural one: that subclassing is the way this kind of
behaviour "should" be achieved. I disagree – IME, APIs that encourage
parametrising small chunks of behaviour are succinct and flexible, and are
often much more pleasant to deal with than subclassing.

For me there are two issues here. Firstly, the creeping cognitive burden –
another symbol in your IDE, another class to look up, more coupling, more
boilerplate, more tiny choices to make about what to call your class and
where to put it, etc.

The second issue is of readability: if I'm reading a form definition which
includes somebody's BookModelChoiceField, I don't know what that does.
Maybe all it does is override label_from_instance, but I don't know that
until I go look it up. However, as a Django user I do know what
ModelChoiceField does, I know the behaviour of the label_func parameter, so
I can take that all in at a glance and move on.

This all lies on a spectrum in that the more places you use your subclass,
the more justification it has for existing. But when subclassing is the
only solution, you end up defining classes that make only tiny changes to
behaviour and that you instantiate in only one place, and to me that's an
opportunity for improvement in an API.

Alex

P.S.

Another way I have dealt with this issue generically is by overriding
ModelChoiceField._get_choices() to return an overridden ModelChoiceIterator
which yields for each choice not a tuple, but a ModelChoice – a tuple
subclass with an "instance" attribute. It's a little convoluted, but it
means that in your template (and wherever else), you have access to the
actual model instance and can do whatever you like there. If you're not
doing custom things in your template it's not that useful, though.

See gist at
https://gist.github.com/AlexHill/4a5583ab8f983044e2ff04458b52ce4a



On Wed, 21 Sep 2016 at 10:09 Tim Graham <timogra...@gmail.com> wrote:

> The approach you suggested was suggested in the thread of ticket you
> mentioned:
> https://groups.google.com/d/topic/django-developers/7DDEX73zVrI/discussion
>
> Brian Rosner: "I am a +1 on a configuration parameter since the
> alternative by subclassing is a bit too involved for something fairly
> trivial."
>
> Why was it rejected? What new arguments are you bringing to the table that
> weren't considered before?
>
> You say that subclassing is a burden, but I'd argue that even redefining
> the field on the model form isn't DRY, at which point what about making the
> customization in the form's __init__()?
>
> self.fields['field_name'].label_from_instance = lambda obj: 'new label'
>
> I think the barrier to violate the Zen of Python ("There should be one--
> and preferably only one --obvious way to do it.") is a bit high here, so
> perhaps you could elaborate on how this is causing maintenance problems?
>
>
> On Tuesday, September 20, 2016 at 9:52:55 PM UTC-4, Lawrence Vanderpool
> wrote:
>>
>> Older related ticket: https://code.djangoproject.com/ticket/4620
>>
>> My rough draft of proposed changes:
>> https://gist.github.com/mekhami/24af779f4f491d3c66e6fd607c2121aa/revisions
>>
>> The problem of setting the label for ModelChoiceField is one that comes
>> up on IRC every once in a while. It's a common enough problem that I think
>> the documentation-recommended solution of subclassing ModelChoiceField and
>> setting label_from_instance (
>> https://docs.djangoproject.com/en/1.10/ref/forms/fields/#modelchoicefield
>> ) is overkill, and probably a maintenance problem.
>>
>> ModelChoiceField already implements an optional callable in the
>> `get_limit_choices_to` function. This change would implement a similar API
>> to allow a callable to be passed in to the constructor rather than having
>> to do the subclassing dance.
>>
>> It'd still be backwards compatible, but the documentation should be
>> changed to reflect the "easier" solution of passing in the callable.
>>
>> The old ticket was labelled wontfix, but I think we should take a look
>> again. I'd love for this to be my first contribution to Django! Thanks for
>> any feedback. And if I forgot something or broke a rule for the ML, I
>> apologize in advance @.@
>>
> --
> 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+unsubscr...@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/f79d0b45-5073-4332-80df-0ca21cba1d98%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/f79d0b45-5073-4332-80df-0ca21cba1d98%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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+unsubscr...@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/CA%2BKBOKxJcd6h0epWYDOby3M7X0Nz_hx0r8jyxA-ayJsFkXdtSQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to