Profile
contains a PointField
. I've used OSMGeoAdmin in the ProfileAdmin, here:
class ProfileAdmin(admin.OSMGeoAdmin):
model = Profile
But can't figure out how to use it in an inline for display in the UserAdmin. I currently have this set up as below:
# User Admin, with Profile attached
class ProfileInline(admin.StackedInline):
model = Profile
can_delete = False
verbose_name_plural = 'Profile' # As only one is displayed in this view
class UserAdmin(UserAdmin):
inlines = (
ProfileInline,
)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Is it possible to use class OSMGeoAdmin in this situation?
GeoDjango is a framework that makes it as easy as possible to build GIS and location aware web applications. You can add it by simply including the gis contrib module in the list of installed apps.
Congratulations on creating your location based web application using GeoDjango, which aims to become a world-class geographic framework for implementing GIS apps. You now have the basic skills that you can use to either add simple geolocation stuff to your applications or create GIS apps.
You’ll create a Shop model that has the following fields: Open the shops/models.py file and add the following code: For the location, you are using the PointField, a GeoDjango-specific geometric field for storing a GEOS Point object that represents a pair of longitude and latitude coordinates.
The 4326 srid is the most popular system used with PostGIS. It’s also known as WGS84, where units are specified in degrees of longitude and latitude. You can refer to spatialreference.org for a Django-powered database of spatial reference systems. Next, add the migration class to execute the above function when you run the migrate command:
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 attached
class 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_plural
class 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.
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},
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With