GeoDjango: Can I use OSMGeoAdmin in an Inline in the User Admin?
Since Django admin fields use widgets, you can override the widget that's automatically set for a PointField
using formfield_overrides. In this case, you can override all PointField
instances to use the OSMWidget class like so:
from django.contrib.gis.forms.widgets import OSMWidget class ProfileInline(admin.StackedInline): model = Profile can_delete = False verbose_name_plural = 'Profile' # As only one is displayed in this view formfield_overrides = { PointField: {"widget": OSMWidget}, }
This would be a good feature to request I guess.
As a workaround, you can take advantage of the fact that an InlineModelAdmin
is quite similar to a ModelAdmin
. Both extend BaseModelAdmin
.
Inheriting from both StackedInline
and ModelAdmin
should not clash too much.
The only issue is that both __init__()
methods take 2 positional arguments and call super().__init__()
without arguments. So whatever the inheritance order, it will fail with TypeError: __init__() missing 2 required positional arguments: 'parent_model' and 'admin_site'
Fortunately, the InlineModelAdmin.__init__()
method, the one we are interested in, is not really verbose nor complex (not too much super().__init__()
calls in cascade).
Here is what it looks like in Django 1.9:
def __init__(self, parent_model, admin_site): self.admin_site = admin_site self.parent_model = parent_model self.opts = self.model._meta self.has_registered_model = admin_site.is_registered(self.model) super(InlineModelAdmin, self).__init__() if self.verbose_name is None: self.verbose_name = self.model._meta.verbose_name if self.verbose_name_plural is None: self.verbose_name_plural = self.model._meta.verbose_name_plural
And here is what its parent (BaseModelAdmin
) looks like in Django 1.9
def __init__(self): overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy() overrides.update(self.formfield_overrides) self.formfield_overrides = overrides
Now let's put it all together:
from django.contrib.admin.options import FORMFIELD_FOR_DBFIELD_DEFAULTS# User Admin, with Profile attachedclass ProfileInline(OSMGeoAdmin, admin.StackedInline): model = Profile can_delete = False verbose_name_plural = 'Profile' # As only one is displayed in this view def __init__(self, parent_model, admin_site): self.admin_site = admin_site self.parent_model = parent_model self.opts = self.model._meta self.has_registered_model = admin_site.is_registered(self.model) overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy() overrides.update(self.formfield_overrides) self.formfield_overrides = overrides if self.verbose_name is None: self.verbose_name = self.model._meta.verbose_name if self.verbose_name_plural is None: self.verbose_name_plural = self.model._meta.verbose_name_pluralclass UserAdmin(UserAdmin): inlines = ( ProfileInline, )admin.site.unregister(User)admin.site.register(User, UserAdmin)
It's not really a satisfying solution as it requires to copy/paste some code from django, which may be different within the version of Django you use, and might be a pain to maintain when upgrading Django. However it should work until it is included in Django as a mix-in or as an InlineModelAdmin
.
Note: the code snippets above are taken from Django 1.9, you should browse github tags to find the snippets corresponding to your version.