views:

107

answers:

2

I have a problem in customizing labels in a Django form

This is the form code in file contact_form.py:

from django import forms

class ContactForm(forms.Form):
    def __init__(self, subject_label="Subject", message_label="Message", email_label="Your email", cc_myself_label="Cc myself", *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)

        self.fields['subject'].label = subject_label
        self.fields['message'].label = message_label
        self.fields['email'].label = email_label
        self.fields['cc_myself'].label = cc_myself_label

    subject = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
    message = forms.CharField(widget=forms.Textarea(attrs={'rows':15, 'cols':80}))
    email = forms.EmailField(widget=forms.TextInput(attrs={'size':'60'}))
    cc_myself = forms.BooleanField(required=False)

The view I am using this in looks like:

def contact(request, product_id=None):
    .
    .
    .
    if request.method == 'POST':
        form = contact_form.ContactForm(request.POST)
        if form.is_valid():
            .
            .
        else:
            form = contact_form.ContactForm(
                subject_label = "Subject",
                message_label = "Your Message",
                email_label = "Your email",
                cc_myself_label = "Cc myself")

The strings used for initializing the labels will eventually be strings dependent on the language, i.e. English, Dutch, French etc.

When I test the form the email is not sent and instead of the redirect-page the form returns with:

<QueryDict: {u'cc_myself': [u'on'], u'message': [u'message body'],
u'email':[u'[email protected]'], u'subject': [u'test message']}>:

where the subject label was before. This is obviously a dictionary representing the form fields and their contents.

When I change the file contact_form.py into:

from django import forms

class ContactForm(forms.Form):
    """
    def __init__(self, subject_label="Subject", message_label="Message", email_label="Your email", cc_myself_label="Cc myself", *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)

        self.fields['subject'].label = subject_label
        self.fields['message'].label = message_label
        self.fields['email'].label = email_label
        self.fields['cc_myself'].label = cc_myself_label
    """
    subject = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
    message = forms.CharField(widget=forms.Textarea(attrs={'rows':15, 'cols':80}))
    email = forms.EmailField(widget=forms.TextInput(attrs={'size':'60'}))
    cc_myself = forms.BooleanField(required=False)

i.e. disabling the initialization then everything works. The form data is sent by email and the redirect page shows up. So obviously something the the init code isn't right. But what?

I would really appreciate some help.

+1  A: 

I think you're approaching the problem the wrong way. You should use the internationalisatoin module instead.

That way you can have your form like this:

class ContactForm(forms.Form):
    subject = forms.CharField(label=_('contact_form_subject'), widget=forms.TextInput(attrs={'size':'60'}))

The Django internationalisation system will automatically insert the correct translation for you if you provide the translation files.

WoLpH
I know internationalization is an option but that doesn't answer my question. How do I modify labels in a form. An option would be to adjust the template using variables and skip modifying the class ContactForm altogether.
Henri
The internationalisation option is _the_ solution for varyating labels so I still recommend using that. However... that is not the problem here, although that would solve it too ;) I'm not sure why it's not working right now, but I have to ask... is the indentation for the `super()` part only wrong in the example? Cause it should be at the same level as `self.fields[...].label = '...'`
WoLpH
The indentation is only wrong here. In the code it is at the same level as self.fields[...].label ...etc. Sorry for the confusion. I have edited the example.The reason I am not using internationalization is that the international string are residing is a database, so the web master/manager can easily add support for new languages for the application. Language support is used for the web texts but also for product descriptions and articles published in various languages.
Henri
The code of the class ContactForm can be seen here:http://www.whitemoorstudio.com/site_media/images_misc/ContactForm.jpg
Henri
The code including errors can be seen here: http://www.whitemoorstudio.com/site_media/images_misc/ContactForm.png
Henri
I solved my problem by creating a template for the form. In that template I can do whatever I want.
Henri
+1  A: 

You should change the form init decleration, that QueryDict tha gets printed is the request.GET or request.POST that you pass as first argument when you initialize the form.

i guess changing this

def __init__(self, subject_label="Subject", ...

to this

def __init__(self, data=None, subject_label="Subject", ... ...):
    super(ContactForm, self).__init__(data, *args, **kwargs)
    ...

will solve your problem.

vinilios
And what will __init__ expect for the data argument? Because when I add this data argument __init__ complains about wanting 2 non-keyword arguments but only getting 1. So what argument should be supplied for data when creating the form object?
Henri
you should also pass it on super init. this: super(ContactForm, self).__init__(*args, **kwargs)should get changed to: super(ContactForm, self).__init__(data, *args, **kwargs). I updated my answer.
vinilios
how about creating the form then? Because now creating a ContactForm object also requires an argument to passed into data.form = ContactForm(data=... What is the argument for data? I thought it could be request.POST but then the initial form complains about all the required fields which are missing.
Henri
set initial argument to None. check the updated answer
vinilios
Thanks very much for your help. Everything seems to work now. The solution creating a template also worked, but this solution is more elegant.
Henri