2

i have python django project where i am using to display all the books and rendering a single book when clicking on each book so django will automatically generate the book details.

so while rendering i want to make the price_upgrade boolean field read only if the user doesn't have a group called author

so my codes like this

class BookAdmin(admin.ModelAdmin):
    list_per_page = 10
    list_display_links = ['name']
    readonly_fields = ('id', 'name', 'city', 'price_upgrade')
    ...
    ...
    ...

def has_change_permission(self, request, obj=None):
        if request.user.groups.all().filter(Group ='author').exists():
            print('author group is there')
        else:
            print('author group is not there')
        #print('request', request.user.groups.all(), type(request.user.groups.all()))
        return True

how can i add the price_upgrade field to readonly_fields if current user doesn't have the group of author else we should remove the price_upgrade field from readonly_fields because he is part of author group so he can edit it

Version python 2.7 django 1.8

Any help appreciated

Learner
  • 8,379
  • 7
  • 44
  • 82
  • I think this answer https://stackoverflow.com/questions/324477/in-a-django-form-how-do-i-make-a-field-readonly-or-disabled-so-that-it-cannot will work for you. – FatmaT Oct 24 '19 at 11:19

2 Answers2

2

You can override the changeform_view like this in your BookAdmin

       def changeform_view(self, request, *args, **kwargs):
            self.readonly_fields = list(self.readonly_fields)
            usergroup = request.user.groups.filter(name__in=['author']).exists()
            if not usergroup:
                self.readonly_fields.append('price_upgrade')

            return super(BookAdmin, self).changeform_view(request, *args, **kwargs)

AOTHER OPTION: Updated you can override the get_readonly_fields method in your Admin

def get_readonly_fields(self, request, obj=None):
    usergroup = request.user.groups.filter(name__in=['author']).exists()
    if not usergroup:
       # since readonly_fields is a tuple we need to append to tuple
        self.readonly_fields = self.readonly_fields + ('price_upgrade',)
    return self.readonly_fields

The issue why it was overriding the value based on the comment is because it was running on the same port (same instance), so made the project up and running in two different port so the issue was not there. Since when your are accessing the same port it will have the same permission for the both users so we need to restart the server.

This was what i found, kindly update if any miss info is there

@Update There is a caching issue is there thats why its overriding the permission, need to find a solution for it, the problem is if you logged in with a different user doesn't have the author group and logout and login with a user has author group will not be able to edit the checkbox, so there is an issue of caching Will update it soon once i found out a solution. If i restart the server it works fine, but restarting the server is not the proper solution.

Related ref

So after going through the issue, found out the solution

def get_readonly_fields(self, request, obj=None):
        readOnlyFields = super(BookAdmin, self).get_readonly_fields(request, obj)
        usergroup = request.user.groups.filter(name__icontains='author').exists()
        if not usergroup:
            readOnlyFields = readOnlyFields + ('price_upgrade',)
        return readOnlyFields
Learner
  • 8,379
  • 7
  • 44
  • 82
arjun
  • 7,230
  • 4
  • 12
  • 29
  • if not request.user in group, so the group where we should mention, the group name is author should we write like request.user in 'author' – Learner Oct 24 '19 at 12:04
  • added a colon at the first line fixed that error, but now global name 'group' is not defined. tried passing the text like request.user in 'author' got another error. May be i am thinking in js perspective – Learner Oct 24 '19 at 12:10
  • @DILEEPTHOMAS try `if not request.user in Group.objects.filter(name ='author')` – arjun Oct 25 '19 at 04:16
  • @ arjun i have updated the answer, and one more issue. to check whether the code is working i open two users at a time in chrome(user has author group) and firefox (user doesnt have author group). now if i refresh in firefox it will work properly but if i refresh chrome the field is disabled but it should be enabled. now if i restart server it and check chrome it works fine, but when in firefox if i refresh its overriding the chrome is it because of any cache issue – Learner Oct 25 '19 at 05:49
  • okay let me check it, since i am new to python dont know is there any inbuilt caching system or anything like that is there or is it because of the method – Learner Oct 25 '19 at 06:08
  • @DILEEPTHOMAS there is another option also you can try this also.check my updated answer – arjun Oct 25 '19 at 06:08
  • so if we use the second way, do we need to do self.readonly_fields.append, because or else it will be overriding the initial values we defined at the top of class is that correct – Learner Oct 25 '19 at 06:10
  • if the user has permission there will be no read_only fields .For this you need to specify readonly_fileds first in your ModelAdmin class – arjun Oct 25 '19 at 06:12
  • okay, let me try it in both ways and will try the testing at the same time on diff users on diff browser and will let u know, thanks for the help :) – Learner Oct 25 '19 at 06:16
  • @ arjun kindly verify and update if anything i missed, so we can close the question by accepting it. It will be helpful for others to find the detailed info if you can add any further to this. Happy Coding :) – Learner Oct 25 '19 at 07:22
  • @ arjun i have updated one issue related to cache, kindly do the peer review otherwise can you update that info on the answer – Learner Oct 30 '19 at 09:02
  • @ arjun updated with the correct solution, kindly review and update. Thanks for the help happy coding :) – Learner Oct 30 '19 at 13:34
0

In the method described above, I had a problem when there were requests from a user who had permissions (in my case custom) and another user who did not have permissions. Hence my solution which dynamically refreshes and checks without the need to restart the server.

Instead of entering sections in the admin model that will always be read-only, we put them in the second line instead of "['dynamic_average_rating']".

    def changeform_view(self, request, *args, **kwargs):
    self.readonly_fields = ['dynamic_average_rating']
    has_perm_edit_slug = request.user.has_perm('places.can_edit_slug')
    if not has_perm_edit_slug:
        self.readonly_fields.append('slug')

    self.readonly_fields = tuple(self.readonly_fields)

    return super(PlaceAdmin, self).changeform_view(request, *args, **kwargs)
JP-Ekuzen
  • 1
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 02 '22 at 22:59