Aditya
Aditya

Reputation: 1104

Django Forms - How to make certain fields readonly except for superuser

I use UserChangeForm and UpdateView, to update user information the UpdateView is only accessible for the owner of the account and superuser. now, I need to make the username and subject fields to be read only when the owner wants to edit their profile info but it will be editable when superuser access wants to edit it.

forms.py

class TeacherUpdateForm(UserChangeForm):
    readonly = ("username", "subject")
    
    class Meta:
        model = Profile
        fields = ["username", "first_name", "last_name", "email", "phonenumber", "address", "subject"]

    def __init__(self, *arg, **kwargs):
        super(TeacherUpdateForm, self).__init__(*arg, **kwargs)
        for x in self.readonly:
            self.fields[x].widget.attrs['disabled'] = 'disabled'

    def clean(self):
        data = super(TeacherUpdateForm, self).clean()
        for x in self.readonly:
            data[x] = getattr(self.instance, x)
        return data

views.py

class TeacherUpdateView(UpdateView):
    model = Profile
    form_class = TeacherUpdateForm
    template_name = "account/update_form.html"

    def get_context_data(self, **kwargs):
        kwargs["user_type"] = "Teacher"
        return super().get_context_data(**kwargs)

    def get_object(self, *args, **kwargs):
        obj = super(TeacherUpdateView, self).get_object(*args, **kwargs)
        if obj.id is self.request.user.id or self.request.user.is_superuser:
            return obj
        else:
            raise PermissionDenied()
    
    def form_valid(self, form):
        form.save()
        return redirect(reverse("index"))

I feel stuck because every solution I see is using get_readonly_fields and it doesn't work on the forms or views. For another info, the subject field is a foreignkey from another model.

so far I can make those field readonly for the owner but it still readonly as well for superuser, I want to make it editable for superuser but not for the owner

Upvotes: 1

Views: 3605

Answers (1)

Aditya
Aditya

Reputation: 1104

forms.py

class TeacherUpdateForm(UserChangeForm):
    class Meta:
        model = Profile
        fields = ["username", "first_name", "last_name", "email", "phonenumber", "address", "subject"]

views.py

class TeacherUpdateView(UpdateView):
    model = Profile
    form_class = TeacherUpdateForm
    template_name = "account/update_form.html"

    def get_context_data(self, **kwargs):
        kwargs["user_type"] = "Teacher"
        return super().get_context_data(**kwargs)

    def get_object(self, *args, **kwargs):
        obj = super(TeacherUpdateView, self).get_object(*args, **kwargs)
        # Restrict type of user who can access UpdateView
        if obj.id is self.request.user.id or self.request.user.is_superuser:
            return obj
        else:
            raise PermissionDenied()

    def get_form(self, form_class=None):
        form = super(TeacherUpdateForm, self).get_form(form_class)
        if not self.request.user.is_superuser:
            # Disable these fields
            form.fields["username"].disabled = True
            form.fields["subject"].disabled = True
        return form

    def form_valid(self, form):
        form.save()
        return redirect(reverse("index"))

Upvotes: 1

Related Questions