Reputation: 445
I'm working on the Django admin site of an online shop, and I'm asked to enable a refund button only to a limited group of admins. The current situation, extremely simplified, is the following:
models.py
class ItemOrder(models.Model)
[various fields and functions]
admin.py
class ItemOrderAdmin(admin.ModelAdmin):
fieldsets = [
...
('Actions', {'fields': ['created', 'modified', 'refund_link']}),
]
...
readonly_fields = [..., 'created', 'modified', 'refund_link']
[other functions]
def refund_link(self, order):
...
At the moment every user with the right to see this page can click on the refund link and refund the order. I need to restrict its visibility/usability only to users who have a specific right. I tried with the @permission_required
decorator, but the link is unusable for every user (it becomes "-" for anyone, even superusers). I also tried adding the get_form
method to the ItemOrderAdmin
class, but the refund link disappears completely for every user. This is how it was implemented:
admin.py
class ItemOrderAdmin(admin.ModelAdmin):
fieldsets = [
...
('Actions', {'fields': ['created', 'modified']}),
]
...
readonly_fields = [..., 'created', 'modified', 'refund_link']
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser: # Will be changed with a more specific right later
kwargs['form'] = EventTicketOrderPersonForm
return super().get_form(request, obj, **kwargs)
[other functions]
def refund_link(self, order):
...
forms.py
class ItermOrderForm(forms.ModelForm):
class Meta:
model = ItemOrder
fields = '__all__'
class Meta:
model = ItemOrder
fieldsets = [
...
('Actions', {'fields': ['created', 'modified', 'refund_link']}),
]
This was copied from the official documentation. I tried various variations of this. Mainly I tried removing the second Meta class in forms.py and the refund_link
from the readonly_fields
in admin.py, but the result is always that the link is missing for every user.
I have to say I'm quite new to Django, and some of the connections it makes between modules are still a bit magical to me. I suspect I'm missing something basic, but I can't find out what it is.
Edit: I managed to make forms work by commenting fieldsets
and readonly_fields
, but the result is far from what I need. Some fields are missing (the ones defined as functions inside ItemOrderAdmin
, e.g. refund_link
), all the fields are editable (only a few should be), and they are not divided into sets. It looks to me that forms are not what I'm looking for, but I'm open to suggestions.
Upvotes: 1
Views: 755
Reputation: 445
I may have found the answer. Instead of specifying the fieldsets
variable at the beginning of the class, I can define the get_fieldsets
method, in this way:
admin.py
class ItemOrderAdmin(admin.ModelAdmin):
...
readonly_fields = [..., 'created', 'modified', 'refund_link']
[other functions]
def get_fieldsets(self, request, obj=None):
fieldsets = [
...
('Actions', {'fields': ['created', 'modified', 'refund_link']}),
]
if request.user.is_superuser:
fieldsets[4][1]['fields'].append('refund_link') # The 4 depends on the fieldsets structure.
return fieldsets
def refund_link(self, order):
...
I'll wait a few hours before approving my answer, in case someone comes up with a better solution, or there are major flaws in mine.
Upvotes: 2