GeoDjango:我可以在用户管理的内联中使用 OSMGeoAdmin 吗?
GeoDjango: Can I use OSMGeoAdmin in an Inline in the User Admin?
Profile
包含一个 PointField
。我在 ProfileAdmin 中使用了 OSMGeoAdmin,这里:
class ProfileAdmin(admin.OSMGeoAdmin):
model = Profile
但无法弄清楚如何在 UserAdmin 中显示的内联中使用它。我目前的设置如下:
# 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)
在这种情况下可以使用 class OSMGeoAdmin 吗?
我想这是一个很好的请求功能。
作为变通方法,您可以利用 InlineModelAdmin
与 ModelAdmin
非常相似这一事实。两者都扩展 BaseModelAdmin
.
从 StackedInline
和 ModelAdmin
继承应该不会有太多冲突。
唯一的问题是两个 __init__()
方法都采用 2 个位置参数并调用 super().__init__()
时不带参数。所以无论继承顺序如何,它都会失败 TypeError: __init__() missing 2 required positional arguments: 'parent_model' and 'admin_site'
幸运的是,我们感兴趣的 InlineModelAdmin.__init__()
方法既不冗长也不复杂(没有太多 super().__init__()
级联调用)。
这是它的样子 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
这是它的父级 (BaseModelAdmin
) 的样子 in Django 1.9
def __init__(self):
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
overrides.update(self.formfield_overrides)
self.formfield_overrides = overrides
现在让我们把它们放在一起:
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)
这并不是一个真正令人满意的解决方案,因为它需要 copy/paste 来自 django 的一些代码,这些代码在您使用的 Django 版本中可能有所不同,并且在升级 Django 时可能很难维护。但是它应该可以工作,直到它作为混入或作为 InlineModelAdmin
.
包含在 Django 中
注意:以上代码片段取自Django 1.9,您应该浏览github标签找到与您的版本对应的片段。
由于 Django 管理字段使用小部件,您可以使用 formfield_overrides. In this case, you can override all PointField
instances to use the OSMWidget class 覆盖为 PointField
自动设置的小部件,如下所示:
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},
}
Profile
包含一个 PointField
。我在 ProfileAdmin 中使用了 OSMGeoAdmin,这里:
class ProfileAdmin(admin.OSMGeoAdmin):
model = Profile
但无法弄清楚如何在 UserAdmin 中显示的内联中使用它。我目前的设置如下:
# 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)
在这种情况下可以使用 class OSMGeoAdmin 吗?
我想这是一个很好的请求功能。
作为变通方法,您可以利用 InlineModelAdmin
与 ModelAdmin
非常相似这一事实。两者都扩展 BaseModelAdmin
.
从 StackedInline
和 ModelAdmin
继承应该不会有太多冲突。
唯一的问题是两个 __init__()
方法都采用 2 个位置参数并调用 super().__init__()
时不带参数。所以无论继承顺序如何,它都会失败 TypeError: __init__() missing 2 required positional arguments: 'parent_model' and 'admin_site'
幸运的是,我们感兴趣的 InlineModelAdmin.__init__()
方法既不冗长也不复杂(没有太多 super().__init__()
级联调用)。
这是它的样子 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
这是它的父级 (BaseModelAdmin
) 的样子 in Django 1.9
def __init__(self):
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
overrides.update(self.formfield_overrides)
self.formfield_overrides = overrides
现在让我们把它们放在一起:
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)
这并不是一个真正令人满意的解决方案,因为它需要 copy/paste 来自 django 的一些代码,这些代码在您使用的 Django 版本中可能有所不同,并且在升级 Django 时可能很难维护。但是它应该可以工作,直到它作为混入或作为 InlineModelAdmin
.
注意:以上代码片段取自Django 1.9,您应该浏览github标签找到与您的版本对应的片段。
由于 Django 管理字段使用小部件,您可以使用 formfield_overrides. In this case, you can override all PointField
instances to use the OSMWidget class 覆盖为 PointField
自动设置的小部件,如下所示:
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},
}