sve*_*ltr 27 python django django-admin
哪个是实现我自己的最佳方式django.contrib.admin.sites.AdminSite?
其实我得到一个问题登记INSTALLED_APPS在django.contrib.admin.autodiscover.如果我使用自定义AdminSite类urls.py,则管理页面上不会显示任何应用程序.
我用一个小黑客修复了这个问题.我写了这堂课:
from django.contrib.admin.sites import site as default_site
class AdminSiteRegistryFix( object ):
'''
This fix links the '_registry' property to the orginal AdminSites
'_registry' property. This is necessary, because of the character of
the admins 'autodiscover' function. Otherwise the admin site will say,
that you havn't permission to edit anything.
'''
def _registry_getter(self):
return default_site._registry
def _registry_setter(self,value):
default_site._registry = value
_registry = property(_registry_getter, _registry_setter)
Run Code Online (Sandbox Code Playgroud)
并实现我的自定义AdminSite,如下所示:
from wltrweb.hacks.django.admin import AdminSiteRegistryFix
from django.contrib.admin import AdminSite
class MyAdminSite( AdminSite, AdminSiteRegistryFix ):
# do some magic
pass
site = MyAdminSite()
Run Code Online (Sandbox Code Playgroud)
所以,我可以用这个site为urls.py.
谁知道更好的方法?因为我以下划线开头访问var,所以它只不过是一个hack.我不喜欢黑客.
编辑:另一种方法是重写django.contrib.admin.autodiscover函数,但在这种情况下,我将有冗余代码.
Lou*_*uis 23
使用从django.contrib.admin.AdminSite项目的管理站点派生的自定义类,而无需编写自定义注册代码来向新类注册模型.当我使用自己的模型使用第三方应用时,我宁愿不必编辑自定义注册码,因为模型是从这些应用中添加或删除的.
你必须选择与用于管理站点到自己的实例的默认类,用自己的类创建创建实例之前 django.contrib.admin的autodiscover函数被调用.我是这样做的:
有一个将执行切换的应用程序.(我使用我core出于自己目的命名的项目专用应用程序.)
两种选择:
Django 1.6到1.9:使用__init__应用程序执行切换.在Django 1.8中,由于下面引用的Django 1.9的更改,您将收到弃用警告.请注意,此方法也适用于1.9,因为下面显示的代码加载的Django模块已在1.9中更改,因此它们不再加载模型.当我使用这个方法时,我的core/__init__.py文件包含:
from django.contrib import admin
from django.contrib.admin import sites
class MyAdminSite(admin.AdminSite):
pass
mysite = MyAdminSite()
admin.site = mysite
sites.site = mysite
Run Code Online (Sandbox Code Playgroud)Django 1.9及以上:使用应用程序的应用程序配置来执行切换.从Django 1.9开始,发布说明如下:
所有模型都需要在已安装的应用程序中定义,或者声明一个显式的app_label.此外,在加载应用程序之前无法导入它们.特别是,无法在应用程序的根包中导入模型.
我更喜欢限制我在根级别执行的导入,以避免加载模型的风险.虽然从使用上述__init__方法的1.9版开始工作,但无法确定1.10或更高版本是否会引入会导致问题的更改.
当我用这个方法的core/__init__.py集合default_app_config = "core.apps.DefaultAppConfig",我有core/apps.py这样的:
from django.apps import AppConfig
class DefaultAppConfig(AppConfig):
name = 'core'
def ready(self):
from django.contrib import admin
from django.contrib.admin import sites
class MyAdminSite(admin.AdminSite):
pass
mysite = MyAdminSite()
admin.site = mysite
sites.site = mysite
Run Code Online (Sandbox Code Playgroud)
虽然可以在版本1.7和1.8中使用此方法,但将它与这些版本一起使用会有点冒险.请参阅下面的注释.
比此列表更早放置此应用程序.(这对于1.7及更高版本来说是绝对必要的.在Django的早期版本中,即使应用程序晚于.它也可能正常工作.但是,请参阅下面的注释.)django.contrib.adminINSTALLED_APPSdjango.contrib.admin
执行交换机的应用程序确实应该是第一个应用程序的INSTALLED_APPS列表,以尽量减少别的东西会抢的价值的机会site,从django.contrib.admin开关之前作出.如果另一个应用程序在切换完成之前设法获得该值,则该其他应用程序将具有对旧网站的引用.希拉里肯定会随之而来.
如果两个应用程序试图安装自己的新默认管理站点类,上述方法将无法正常工作.这必须根据具体情况处理.
未来的Django版本可能会破坏这种方法.
对于1.9之前的版本,我更喜欢使用__init__app配置进行站点切换,因为初始化文档表明ready()app配置的方法相对较晚.时间之间的应用程序的模块被加载,时间ready()被调用时,模型已经加载,并且在某些情况下,这可能意味着一个模块抓住的值site从django.contrib.admin 之前 ready被调用.为了最大限度地降低风险,我让应用程序的__init__代码进行切换.
我相信版本1.7和1.8中存在的风险以及我通过__init__尽可能早地执行站点切换而避免的风险在1.9中不存在.在加载所有应用程序之前,禁止每个人加载模块.因此,在ready列出的第一个应用程序的回调中进行切换INSTALLED_APPS应该是安全的.我已经将一个大项目升级到1.9并使用了app配置方法,没有任何问题.
引自https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#customizing-the-adminsite-class
但是,如果您想使用自定义行为设置自己的管理站点,则可以自由地将AdminSite子类化并覆盖或添加您喜欢的任何内容.然后,只需创建AdminSite子类的实例(与实例化任何其他Python类的方式相同),并使用它注册模型和ModelAdmin子类,而不是使用默认值.
我想这是最明确的方法,但它也意味着您需要更改应用程序admin.py文件中的注册码.
在使用您自己的AdminSite实例时,实际上不需要使用自动发现,因为您可能会导入myproject.admin模块中的所有每个应用程序的admin.py模块.
假设似乎是,一旦您开始编写自定义管理站点,它就会变得非常具体项目,并且您事先知道要包含哪些应用程序.
所以,如果你不想使用上面的hack,我真的只看到这两个选项.将所有注册调用替换为自定义管理站点,或在管理模块中明确注册模型.
从Django 2.1开始,有一个“现成的”解决方案:https : //docs.djangoproject.com/en/2.1/ref/contrib/admin/#overriding-the-default-admin-site
from django.contrib import admin
class MyAdminSite(admin.AdminSite):
...
Run Code Online (Sandbox Code Playgroud)
现在,通过将自己的AdminConfig添加到已安装的应用程序来完成自定义管理站点的交换。
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
Run Code Online (Sandbox Code Playgroud)
INSTALLED_APPS = [
...
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]
Run Code Online (Sandbox Code Playgroud)
注意AdminConfig和SimpleAdminConfig之间的区别,后者后者不会触发admin.autodiscover()。我目前正在项目中使用此解决方案。
小智 5
在 Django 3.2 中实现站点范围的自定义 AdminSite 时遇到了同样的问题,我找到了一个解决方法来使它工作。
似乎应该相应地更新文档。
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
Run Code Online (Sandbox Code Playgroud)
这引发了一个异常:
RuntimeError: 'myproject.apps' declares more than one default AppConfig: 'AdminConfig', 'MyAdminConfig'.
它是通过导入django.contrib.admin.apps而不是解决django.contrib.admin.apps.AdminConfig:
from django.contrib.admin import apps
class MyAdminConfig(apps.AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
Run Code Online (Sandbox Code Playgroud)
然后异常继续:
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: admin
这是由settings.py配置引起的:
INSTALLED_APPS = [
'myproject.apps.MyAdminConfig', #replaces django.contrib.admin
...
Run Code Online (Sandbox Code Playgroud)
它可以通过从设置中删除“MyAdminConfig”来解决:
INSTALLED_APPS = [
'myproject.apps', #replaces django.contrib.admin
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15640 次 |
| 最近记录: |