Django + Crispy form - Readonly field for specific usergroup/user without Javascript : possible?

I know how to set a field readonly using the helper, but I'd like to disable values changes for specific users. The only way I found consists in adding a condition in the the form taking in account the user.is_staf or user.is_superuser.

Form call in views.py

s_form = stock_inline_formset(
        instance=product, form_kwargs={'empty_sst': empty_sst, 'user_is_staff': 
        user.is_staff})

Condition in forms.py

class SstStockForm(forms.ModelForm):

    class Meta:
        model = SstStock
        fields = ('qty', 'warehouse', 'maxsst', 'adresse', 'pua', 'cau')

    def __init__(self, *args, **kwargs):
        self.empty_sst = kwargs.pop('empty_sst', None)
        self.user_is_staff = kwargs.pop('user_is_staff', None)
        super().__init__(*args, **kwargs)
        if not self.user_is_staff:
            self.fields['qty'].widget.attrs = {'readonly': 'readonly'}
            self.fields['pua'].widget.attrs = {'readonly': 'readonly'}
            self.fields['cau'].widget.attrs = {'readonly': 'readonly'}
            [...]

Is it the better way ? Otherwise I could do it with JS using the same condition based on the user for setting the input field readonly. I didn't find any ressource talking about this.

If this is working but you want a different set of users to be made read-only, why not just pass

make_readonly = # boolean derived from user
s_form = stock_inline_formset(
    instance=product,
    form_kwargs={'empty_sst': empty_sst, 'user_is_staff': make_readonly }
)

where make_readonly is a boolean generated in your view by interrogating request.user or any other information derived from the user's details.

If you want to act differently on different forms in the formset, pass request.user itself rather than a boolean derived from it, and them each form can make its own determination of whether to be read-only or not.

Back to Top