xpanta
xpanta

Reputation: 8418

Django, set ChoiceField in form, after creation

I want to display a form with some customized user data in it. More specifically I want to fill a forms.ChoiceField with different data for each user.

This is my Form:

class WallPostForm(forms.Form):
    text = forms.CharField(label=u'', widget=TinyMCE(attrs={'cols': 70, 'rows': 5}))
    relates_to = forms.ChoiceField(label=u'Relates to', choices=[], widget=forms.Select(), required=False)

    def __init__(self, data):
        self.fields['relates_to'] = forms.ChoiceField(label=u'Relates to', choices=data, widget=forms.Select(), required=False)
        super(WallPostForm, self).__init__()

And this is how I am calling this:

user = get_object_or_404(User, username=username)
data = UserTopics.objects.filter(user=user, result=0).values('id', 'topic__name')[:10]
form = WallPostForm(data)

I get a 'WallPostForm' object has no attribute 'fields' error.

What am I doing wrong?

Upvotes: 1

Views: 2997

Answers (3)

Mordi
Mordi

Reputation: 691

You can use "initial" parameter, see the docs: https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.initial

Upvotes: -1

Daniel Roseman
Daniel Roseman

Reputation: 599480

As an addition to Jack's answer, you're probably better off just replacing the choices attribute, rather than the whole field:

def __init__(self, *args, **kwargs):
    relates_to_choices = kwargs.pop('relates_to_choices')
    super(WallPostForm, self).__init__(*args, **kwargs)
    self.fields['relates_to'].choices = relates_to_choices

(I renamed the variable, it won't be a queryset.)

Upvotes: 4

Jack Shedd
Jack Shedd

Reputation: 3531

Django sets up the form's fields property in the __init__.

So just swap your code:

def __init__(self, data):
    super(WallPostForm, self).__init__()
    self.fields['relates_to'] = forms.ChoiceField(label=u'Relates to', choices=data, widget=forms.Select(), required=False)

Though, you probably shouldn't override a Form's __init__ like that. Django's form system expects the data arg in init to contain the data for the form, not a queryset you're using for a choices field.

I'd override it differently:

def __init__(self, *args, **kwargs):
    relates_to_queryset = kwargs.pop('relates_to_queryset')
    super(WallPostForm, self).__init__(*args, **kwargs)
    self.fields['relates_to'] = forms.ChoiceField(label=u'Relates to', choices=relates_to_queryset, widget=forms.Select(), required=False)

Then call it:

form = WallPostForm(request.POST or None, relates_to_queryset=data)

Upvotes: 3

Related Questions