Search code examples
pythondjangodjango-modelsuser-profile

How to make model objects uneditable after first submission by users


I have a profile model all set up. I have also been able to render the data to the template, however, this is currently editable by logged in users.

My plan, however, is to give users one-off access to fill their data themselves, and once they submit it, such data can not be edited by them except user with is_staff or superadmin privileges, even though they are going to see their data in their profile view.

Is this possible? If yes, what strategy and/or example can I follow as I have no idea whatsoever on how to go about this.

views.py

@transaction.atomic
def edit_profile(request):
    if request.method == 'POST':
        user_form = UserForm(request.POST, instance=request.user)
        employee_form = EmployeeProfileUpdateForm(request.POST, instance=request.user.profile)
        if user_form.is_valid() and employee_form.is_valid():
            user_form.save()
            employee_form.save()
            messages.success(request, 'Account successfully updated!')
            return render(request, 'accounts/update-profile.html')
        else:
            messages.warning(request, 'Please correct the error(s) below')
    else:
        user_form = UserForm(instance=request.user)
        employee_form = EmployeeProfileUpdateForm(instance=request.user.profile)
    return render(request, 'accounts/update-profile.html', {
        'user_form': user_form,
        'employee_form': employee_form,
    })

Solution

  • If you use the generic class based views provided by Django it's fairly simple. The mixin UserPassesTestMixin adds a method test_func to a view that you can use to return True or False if the user has permission or not

    from django.views.generic import CreateView, UpdateView, DetailView
    from django.contrib.auth.mixins import UserPassesTestMixin
    
    
    class ProfileCreateView(CreateView):
        # Used for creation - has no special permissions
        model = Profile
    
    
    class ProfileDetailView(DetailView):
        # Used for viewing - has no special permissions
        model = Profile
    
    
    class ProfileUpdateView(UserPassesTestMixin, UpdateView):
        # Used for updating - requires a user be superuser or staff
        model = Profile
    
        def test_func(self):
            return self.request.user.is_superuser or self.request.user.is_staff