Tuesday, December 22, 2020

Re: MultipleChoiceField form bug?

Hi,

On Dec/22/2020, Benny M wrote:
> That's correct. I am using a class variable since there doesn't seem
> to be a DRY - or at least not messy - way of manipulating this from
> __init__.

It's easy to make this mistake. I was bitten by something similar in a
class based view generating a queryset...

> That said, your explanation makes sense and does answer the "why" of
> this. If there's a way of defining forms inside __init__ I haven't
> found it… which is not to say that it doesn't exist.

Yes, you can

> Here's an example of what I'm referring to: (Pardon my poorly labeled
> model/form names)
>
> ```
> class M2MForm(forms.ModelForm):
> """ Populate/update M2MModel name and m2m references """
> REF_OPTIONS = ((r.id, r.name) for r in RefModel.objects.all())
>
> ref_models = forms.MultipleChoiceField(
> widget=forms.SelectMultiple,
> choices=REF_OPTIONS,
> required=False
> )
>
> class Meta:
> model = M2MModel
> fields = ['name']
> ```


Try something like:

```
class M2MForm(forms.ModelForm):
def __init__(*args, **kwargs):
super().__init__(*args, **kwargs)

# At this point self.fields['name'] already exist...
# ...if you overwriteself.fields['name'] careful
# because you need to save it in save()
#
# self.fields gets created by the __init__() method of
# the parent class (actually grandparent I think :-) )

""" Populate/update M2MModel name and m2m references """
REF_OPTIONS = ((r.id, r.name) for r in RefModel.objects.all())


# this would add the field 'ref_models' in the form, but save()
# will not save. You can overwrite save and save it yourself
self.fields['ref_models'] = forms.MultipleChoiceField(
widget=forms.SelectMultiple,
choices=REF_OPTIONS,
required=False
)

class Meta:
model = M2MModel
fields = ['name']
```

I would look at not using forms.MultipleChoiceField and use
forms.ModelMultipleChoiceField(): then you should be able to pass
queryset (first argument for the ModelMultipleChoiceField) and avoid the
REF_OPTIONS=... line

Let me know what you find :-)

Cheers,

>
> > On Dec 22, 2020, at 9:31 AM, Carles Pina i Estany <carles@pina.cat> wrote:
> >
> >
> >
> > Hi,
> >
> > On Dec/22/2020, Benny M wrote:
> >
> >> I've ran into some unexpected behavior while testing a ModelForm with
> >> a MultipleChoiceField and am trying to determine if this is a bug, or
> >> if maybe I'm doing something out of the ordinary.
> >
> > I think that I might guess what it is. If I could see the code it might
> > be easier.
> >
> > Are you doing something like:
> >
> > class SomeForm(forms.ModelForm):
> > some_field_options = a_dynamic_expression_that_queries_the_DB
> >
> > def __init__(*args, **kwargs):
> > your code
> >
> > So using a class variable instead of an instance variable?
> >
> > Class variables are initialised on "startup" (I'm simplifying) and only
> > once (and might be used via __new__ on ModelFormMetaclass probably, read
> > and validated).
> >
> > Either way, if it's not what I've guessed and you paste some code it
> > might help me / someone else to understand it better.
> >
> > I had once a bug because of using datetime.now() in a class variable
> > when I wanted it the "now" that the view was used not the "now" when the
> > application was started up.
> >
> > --
> > Carles Pina i Estany
> > https://carles.pina.cat
> >
> > --
> > You received this message because you are subscribed to the Google Groups "Django users" group.
> > To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
> > To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/20201222153133.GA31856%40pina.cat.
>
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CH2PR14MB39136CDA719529325B91F0E3C0DF0%40CH2PR14MB3913.namprd14.prod.outlook.com.
--
Carles Pina i Estany
https://carles.pina.cat

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/20201223000345.GA24427%40pina.cat.

No comments:

Post a Comment