I have a django form with a choicefield, where I dynamically load some choices into the field:
class EntryForm(forms.Form):
project = forms.ChoiceField()
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(EntryForm, self).__init__( *args, **kwargs)
CHOICES2=[]
for x in Project.objects.all() :
if user in x.users.all():
CHOICES2.append((x.name,x.name))
CHOICES1 = [(x.name,x.name) for x in Project.objects.all()]
print CHOICES2==CHOICES1 #this is True in this case
self.fields['project']=forms.ChoiceField(choices=CHOICES2)
The form is loaded into the template with {{form.as_table}}. The form does not show a dropdown for the project field. Now the strange thing: if I change the last line to:
self.fields['project']=forms.ChoiceField(choices=CHOICES1)
it works, although the print statement of the "=="" comparison returns True (the lists are purposely the same - this is just for testing). I really have no idea how this can even work technically.
Edit - my project model:
class Project(BaseModel):
name = models.CharField(max_length=80)
users = models.ManyToManyField(User)
I think you have to use queryset argument, which is mandatory: https://docs.djangoproject.com/en/1.8/ref/forms/fields/#django.forms.ModelChoiceField.queryset
ChoiceField must be declared with (queryset=None), and in the __init__ method you complete the query:
https://docs.djangoproject.com/en/1.11/ref/forms/fields/#fields-which-handle-relationships
The problem could be about the execution order of the queries, or the cache of non-lazy queries.
And I agree with little_birdie: the field already exists.
Your field named project already exists and there's no need to construct another one as you are doing. It's better to just set the choices on the existing field:
self.fields['project'].choices = CHOICES2
But maybe you'd be better off using a ModelChoiceField:
project = ModelChoiceField(queryset=Project.objects.none())
and then set the queryset you want in init like so:
self.fields['project'].queryset=Project.objects.filter(users__in=[user])
..which should give you a list of all projects associated with user.