instantiate a django form in readonly mode in a view function

74 views Asked by At

I have a django 4 form having some widgets for the user to select some values:

from django import forms
from .app.model import MyModel
from bootstrap_datepicker_plus.widgets import DatePickerInput

class FooForm(forms.ModelForm):
   # stuff
    class Meta:
        model = FooModel
        fields = [
            "user_id",
            "created_at",
            "some_other_field",
        ]

        widgets = {
            "user_id": forms.NumberInput(),
            "created_at": DatePickerInput(),
            "some_other_field": forms.NumberInput(),
        }

I instantiate that form in several functions in the views.py file:

my_form_instance = forms.FooForm(
    data=data,
    user=request.user,
)

One function create_or_edit_foo() for creating a new or editing an existing record. And another function delete_foo() to delete a record. In the deletion function (used by a specific endpoint /foo/12/delete), I want to display the form but in read-only mode.

How could I achieve that?

I know I can add attrs={'readonly': True,} in each of the widget to make it non-editable. But this will also apply to the form instances used by the create_or_edit function in my views.

I'm using django 4.2 on Ubuntu 22.04 with Python 3.10.6.

2

There are 2 answers

0
cd187 On BEST ANSWER

For KISS, you Can use named argument.

def delete_foo():
    my_form_instance = formes.fooForm(
        data = data,
        User = request.user,
        delete = True,
    )

And in your form :

class FooForm(forms.ModelForm):
    class Meta:
        model = FooModel
        fields = [
            "user_id",
            "created_at",
            "some_other_field",
        ]

        widgets = {             
            "user_id":forms.NumberInput(),
            "created_at": DatePickerInput(),
            "some_other_field": forms.NumberInput(),
        }

    def __init__(self, *args, delete=None, **kwargs):
        super(fooForm, self).__init__(*args, **kwargs)
        if delete:
            for field_name in self.fields : 
                self.fields[field_name].widget.attrs['readonly'] = True


    
1
Chris Curvey On

why not subclass your form to create a Delete-specific version

class MyDeleteForm(MyForm):
   def __init__(self, *args, *kwargs):
       super().__init__(*args, **kwargs)
       # set your read-only attributes here

then in your delete view, use MyDeleteForm