Changes between Initial Version and Version 1 of Ticket #11183


Ignore:
Timestamp:
Sep 11, 2009, 6:01:08 AM (15 years ago)
Author:
Luke Plant
Comment:

Thanks for your work debugging this. If you could create a regression test that corners the problem, that would be great. Put it in 'tests/regressiontests/forms/regressions.py' (unless you can find a better place for it).

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #11183

    • Property Needs tests set
  • Ticket #11183 – Description

    initial v1  
    33
    44== Detail ==
    5 When a base_field in a form points to a Select widget, the widget contains a choices attribute.  During initialiazation of a !ModelChoiceField, a !ModelChoiceIterator is created and the widget's choices attribute is set to point to it.  This is all done by the following line from !ModelChoiceField::__init__();
     5When a base_field in a form points to a Select widget, the widget contains a choices attribute.  During initialiazation of a !ModelChoiceField, a !ModelChoiceIterator is created and the widget's choices attribute is set to point to it.  This is all done by the following line from `ModelChoiceField::__init__()`:
     6{{{
    67        self.queryset = queryset
    7 
    8 When BaseForm:__init__() runs, it does a deepcopy of self.base_fields.  When copying the fields, we call the Widget::__deepcopy__() method.  However, this method copies only the attributes and does not copy the !ModelChoiceIterator that a select widget points to.  I think that a copy should be made of this !ModelChoiceIterator, and furthermore, I think that after making the copy, the newly copied !ModelChoiceIterator's 'field' attribute needs to be updated so that it points to the copied field whose deepcopy caused it to be copied. 
     8}}}
     9When `BaseForm:__init__()` runs, it does a deepcopy of self.base_fields.  When copying the fields, we call the `Widget::__deepcopy__()` method.  However, this method copies only the attributes and does not copy the !ModelChoiceIterator that a select widget points to.  I think that a copy should be made of this !ModelChoiceIterator, and furthermore, I think that after making the copy, the newly copied !ModelChoiceIterator's 'field' attribute needs to be updated so that it points to the copied field whose deepcopy caused it to be copied. 
    910
    1011I encountered this issue when I tried to override the queryset for a !ModelChoiceField with a line like this in the render() function of a widget that derives from a Select widget.  Here is some example code that my usage:
     
    2728
    2829I made a patch to my code that seems to work.  However, I find the patch kind of ugly and I suspect someone that understands the code better than me might want to do this a different way.  I did two things:
    29   * Created a __deepcopy__() method for the Select widget, which does the same thin that Widget::__deepcopy__() does, but also calls copy on the self.choices field
    30   * Created a small loop that follows the deepcopy in BaseForm:__init__(), which runs through all fields that were copied, and if the field contains a'widget' attribute and  that widget attribute contains a 'choices' attribute and that 'choices' attribute contains a 'field' attribute, then it sets that 'field' attribute point to the newly copied field.  This is the part that I think is pretty ugly. 
     30  * Created a `__deepcopy__()` method for the Select widget, which does the same thin that `Widget::__deepcopy__()` does, but also calls copy on the self.choices field
     31  * Created a small loop that follows the deepcopy in `BaseForm:__init__()`, which runs through all fields that were copied, and if the field contains a'widget' attribute and  that widget attribute contains a 'choices' attribute and that 'choices' attribute contains a 'field' attribute, then it sets that 'field' attribute point to the newly copied field.  This is the part that I think is pretty ugly. 
    3132
    3233The attached svn diff shows the patch.
    3334
    3435I ran the django testsuite with the command ./runtests.py --settings=settings and all tests passed and I have verified via my own debugging that this solves my problem.
    35 }}}
    36 
Back to Top