Opened 13 years ago

Last modified 3 years ago

#17881 new New feature

Implement BaseModelAdmin.get_raw_id_fields, similar to get_readonly_fields

Reported by: Aymeric Augustin Owned by: nobody
Component: contrib.admin Version: 1.4-beta-1
Severity: Normal Keywords: raw_id_fields
Cc: kmike84@…, romain.garrigues.cs@…, elonzh Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In order to prevent massive drop downs for related fields when the related model has lots of items, I'd like to add such fields automatically to raw_id_fields.

I've managed to make them read only by implementing the following get_readonly_fields method in the base class that all my ModelAdmin classes inherit:

MODELS_WITH_TOO_MANY_INSTANCES_FOR_ADMIN_SELECT = [
    'auth.User',
    # ...
}

class ModelAdmin(admin.ModelAdmin):

    def get_readonly_fields(self, request, obj=None):
        explicit_readonly_fields = super(ModelAdmin, self).get_readonly_fields(request, obj)
        automatic_readonly_fields = self.related_fields_with_too_many_instances()
        return tuple(set(explicit_readonly_fields) | set(automatic_readonly_fields))

    def related_fields_with_too_many_instances(self):
        fields = []
        for f in self.model._meta.fields:
            # If the field isn't shown anyway, don't bother.
            if self.fields and not f.name in self.fields:
                continue
            # If we made the field editable by id, that means we want to edit it, even if it's impractical
            if f.name in self.raw_id_fields:
                continue
            # If the field is a ForeignKey to a blacklisted model, make it read only.
            if isinstance(f, (django_models.ForeignKey, django_models.ManyToManyField)):
                related_model = '%s.%s' % (f.rel.to._meta.app_label, f.rel.to._meta.object_name)
                if related_model in MODELS_WITH_TOO_MANY_INSTANCES_FOR_ADMIN_SELECT:
                    fields.append(f.name)
        return fields

However, power users occasionally complain that they can no longer edit these fields... which is why I'd like a get_raw_id_fields method that I could override.

Attachments (1)

17881-poc.patch (2.0 KB ) - added by Aymeric Augustin 13 years ago.

Download all attachments as: .zip

Change History (12)

comment:1 by Aymeric Augustin, 13 years ago

Has patch: set

I'm uploading an untested patch showing the idea.

It'd be nice if get_raw_id_fields accepted an optional obj argument, but apparently, this information isn't available in the formfield_for_* methods. This needs more investigation.

by Aymeric Augustin, 13 years ago

Attachment: 17881-poc.patch added

comment:2 by Julien Phalip, 13 years ago

Needs documentation: set
Needs tests: set
Triage Stage: UnreviewedAccepted

comment:3 by Mikhail Korobov, 13 years ago

Cc: kmike84@… added

comment:4 by Collin Anderson, 10 years ago

Keywords: raw_id_fields added

comment:5 by Collin Anderson, 10 years ago

Keywords: raw-id-fields added; raw_id_fields removed

comment:6 by Collin Anderson, 10 years ago

Keywords: raw_id_fields added; raw-id-fields removed

comment:7 by Romain Garrigues, 8 years ago

I was wondering the other day why the default Django admin widget for related fields is a drop-down by default, instead of an autocomplete (as we can have with raw_id_field option), when my Django admin page was crashing down.
I understand that it's more convenient with a drop-down when you have few data, but there is a real risk for Django to crash / expose a lot of data through this feature, and that's not what we are used to with Django.
Usually, default choices in the whole framework are "safe".
@aaugustin, I guess you are not working on it right now, as this ticket is 4 years old.
Do you think it make sense to change this default behaviour, or it has too many impacts?

comment:8 by Romain Garrigues, 8 years ago

Cc: romain.garrigues.cs@… added

comment:9 by Tim Graham, 8 years ago

The ticket for adding a more usable autocomplete widget is #14370. We might consider changing the default to that widget at some point, but it's not a decision to make lightly.

Feel free to work on this ticket if you like.

comment:10 by Fabien Schwob, 8 years ago

Is anyone working on this ticket or can I work on it ?

comment:11 by elonzh, 3 years ago

Cc: elonzh added
Note: See TracTickets for help on using tickets.
Back to Top