user6806523
user6806523

Reputation:

How to add a custom field in django model form?

I'm trying to add a readonly field in a form.

The model Folder is registered in admin site. The FolderAdminForm defines the custom field statistics. There isn't statistcs field in the Folder model, I just want to put some readonly data on the form. This data is defined in the template.

But I get a error whenever the user doesn't have edit permission. If the user only have the view permission,this error is raised:

AttributeError: Unable to lookup 'statistics' on Folder or FolderAdmin

Here is my code:

class CustomWidget(forms.Textarea):
    template_name = 'widget.html'


class FolderAdminForm(forms.ModelForm):
    class Meta:
        model = Folder
        fields = ('field1', 'field2', 'field3',)

    statistics = forms.Field(
        widget=CustomWidget,
        label='Estatísticas',
        help_text='Estatísticas da pasta',
    )

Upvotes: 2

Views: 7688

Answers (2)

user6806523
user6806523

Reputation:

The error only occurred whenever I tried to open a folder instance without edit permission (i.e. with read only permission). Therefore, django consider the statistics field as a read only field and then search for a label for this field. Django look for this label in Model, ModelAdmin. Since none of them has the 'statistics' attribute, the error is raised. So, this worked for me:

 class FolderAdminForm(forms.ModelForm):
    class Meta:
        model = Folder
        fields = ('field1', 'field2', 'field3',)

        labels = {'statistics': 'Estatísticas'}

    statistics = forms.Field(
        widget=CustomWidget,
        label='Estatísticas',
        help_text='Estatísticas da pasta',
    )

Therefore, whenever django looks for a label for statistics, it finds this label and the error is not raised. I don't know why it doesn't recognize the label passed as a Field parameter.

Upvotes: 1

Ralf
Ralf

Reputation: 16515

According to the last part of this answer, you could try to override the forms __init__() method and assign the fields initial attribute.

This could look like:

def __init__(self, *args, **kwargs):
        # only change attributes if an instance is passed            
        instance = kwargs.get('instance')
        if instance:
            self.base_fields['statistics'].initial = 'something'
        super().__init__(*args, **kwargs)

Does this work for you?

Upvotes: 4

Related Questions