Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django admin - dynamic way of defining list_editable

Tags:

django-admin

My goal is to make some fields editable in the list view. But the problem is that the fields are determined dynamically using get_list_display. Moveover, I would like to define the elements of the list_editable to be dynamic as well. However, Django does not seem to provide any method like get_editable_list. Is it made deliberately ? How can this be achieved ?

Now my code looks like this:

class MyModelAmdin(admin.ModelAdmin):

list_editable = ('field1')
# change_list_template = "files_changelist.html"

def get_list_display(self, request):
    if request.user.is_superuser:
        list_display = ('field1', 'field2',)
    else:
        list_display = ('field1',)
    return list_display

Django (justfully) complains that some of the fields which are not included in the list_display are included in the list_editable. Any way ouy?

like image 381
Edgar Navasardyan Avatar asked Nov 05 '25 04:11

Edgar Navasardyan


1 Answers

Good question!! Required a bit of digging in the code, but...

Django does not seem to provide any method like get_editable_list

Yes, this is correct. Django doesn't provide any built in method to do this.

Is it made deliberately ?

I'm not sure, it could be an oversight, but I suspect not. The check that makes sure there is nothing in list_editable that isn't in list_display is run right at the beginning when django starts up, you can't even runserver with this condition. The fact that it is checked in this way, rather than just raising a normal error, makes me think there is good reason to make absolutely certain this condition is held. Adding a dynamic way to set list_editable would make such a check impossible.

How can this be achieved ?

There are a few methods inside ModelAdmin which use self.list_editable. You could reimplement them to use your own self.get_list_editable(request) method. I think the easiest way however would be to overwrite changelist_view and set list_editable before anything else, then all the other methods will be using the correct list_editable e.g:

class MyModelAdmin(admin.modelAdmin):
    list_editable=()  # so the check passes - or can just omit this line completely

    def get_list_editable(self, request):
        # whatever you want here

    def changelist_view(self, request, extra_context=None):
        self.list_editable = self.get_list_editable(request)
        return super().changelist_view(request, extra_context)

Just test thoroughly and make 100% sure that your get_list_editable and get_list_display methods won't lead to a situation where you have something in list_editable that is not in list_display.

like image 101
tim-mccurrach Avatar answered Nov 09 '25 09:11

tim-mccurrach



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!