Changes between Initial Version and Version 1 of Ticket #31295, comment 3


Ignore:
Timestamp:
02/25/2020 05:02:54 PM (8 months ago)
Author:
Aurélien Pardon
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #31295, comment 3

    initial v1  
    77
    88class MyForm(forms.Form):
    9     my_form_field = forms.ModelChoiceField(MyModel.objects.all(), , empty_label=None)
     9    my_form_field = forms.ModelChoiceField(MyModel.objects.all(), empty_label=None)
    1010
    1111my_form = MyForm()
     
    1919
    2020Here is what I understand:
    21 1) The code you sent, where {{{ChoiceWidget.choices}}} is evaluated and saved into a {{{list}}} is executed at the initialization of the widget (which is executed at the initialization of the field at the declaration of the form).
    22 2) But! a {{{ModelChoiceField}}} override {{{self.choices}}}  [https://github.com/django/django/blob/271fdab8b78af558238df51c64b4d1c8dd0792bb/django/forms/models.py#L1225-L1227 here] (it makes perfect sense: the choices have to be evaluated everytime the form is instanciated).
    23 3) As the choices are bundled in a {{{ModelChoiceIterator}}}/{{{.iterator()}}}, when rendering the form, there is a test about the {{{required}}} attribute that try to [https://github.com/django/django/blob/ffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b/django/forms/widgets.py#L699 fetch the first value of the queryset]:
     211. The code you sent, where {{{ChoiceWidget.choices}}} is evaluated and saved into a {{{list}}} is executed at the initialization of the widget (which is executed at the initialization of the field at the declaration of the form).
     222. But! a {{{ModelChoiceField}}} override {{{self.choices}}}  [https://github.com/django/django/blob/271fdab8b78af558238df51c64b4d1c8dd0792bb/django/forms/models.py#L1225-L1227 here] (it makes perfect sense: the choices have to be evaluated everytime the form is instanciated).
     233. As the choices are bundled in a {{{ModelChoiceIterator}}}/{{{.iterator()}}}, when rendering the form, there is a test about the {{{required}}} attribute that try to [https://github.com/django/django/blob/ffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b/django/forms/widgets.py#L699 fetch the first value of the queryset]:
    2424{{{#!python
    2525class Select(ChoiceWidget):
     
    2929        first_choice = next(iter(self.choices), None)
    3030}}}
    31 4) {{{ModelChoiceIterator.__iter__}}} [https://github.com/django/django/blob/ffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b/django/forms/models.py#L1148-L1156 is called]. If {{{empty_label}}} is {{{not None}}}, everything is fine, as the {{{next()}}} grabs the empty label, without additional request to the database. But if {{{empty_label}}} is {{{None}}} (and if there is no prefetch to the queryset), an additional request is made (code is changed lightly to illustrate the bug):
     314. {{{ModelChoiceIterator.__iter__}}} [https://github.com/django/django/blob/ffcf1a8ebfbdc8e3afac84aed88d6ed29a57c72b/django/forms/models.py#L1148-L1156 is called]. If {{{empty_label}}} is not {{{None}}}, everything is fine, as the {{{next()}}} grabs the empty label, without additional request to the database. But if {{{empty_label}}} is {{{None}}} (and if there is no prefetch to the queryset), an additional request is made (code is changed lightly to illustrate the bug):
    3232{{{#!python
    3333    def __iter__(self):
Back to Top