我需要在Django Admin中管理多个数据库。我的两个名为“local”和“server”的数据库在设置文件中定义。由于Django不允许使用不同的ModelAdmin
多次添加相同的模型,因此我创建了两个admin.AdminSite
的实例。
以下是admin.py
文件的代码:
from core.models import MyModel
from django.contrib import admin
server_site = admin.AdminSite('server')
local_site = admin.AdminSite('local')
class MultiDBModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# Tell Django to save objects to the 'other' database.
obj.save(using=self.using)
def delete_model(self, request, obj):
# Tell Django to delete objects from the 'other' database
obj.delete(using=self.using)
def get_queryset(self, request):
# Tell Django to look for objects on the 'other' database.
return super(MultiDBModelAdmin1, self).get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
# Tell Django to populate ForeignKey widgets using a query
# on the 'other' database.
return super(MultiDBModelAdmin1, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# Tell Django to populate ManyToMany widgets using a query
# on the 'other' database.
return super(MultiDBModelAdmin1, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
class MultiDBModelAdmin1(MultiDBModelAdmin):
# A handy constant for the name of the alternate database.
using = 'server'
class MultiDBModelAdmin2(MultiDBModelAdmin):
# A handy constant for the name of the alternate database.
using = 'local'
local_site.register(MyModel, MultiDBModelAdmin1)
server_site.register(MyModel, MultiDBModelAdmin2)
这是urls.py
文件:
from django.conf.urls import patterns, include, url
from core.admin import local_site, server_site
urlpatterns = patterns('',
url(r'^admin/', include(local_site.urls)),
url(r'^serveradmin/', include(server_site.urls)),
[...]
)
我可以使用admin/
和serveradmin/
网址访问管理面板,但内容非常相似:管理面板使用的是“本地”数据库,无论管理面板是什么访问。为什么Django不歧视这两个?
答案 0 :(得分:2)
您可以覆盖get_queryset方法并使用过滤器来允许将admin上的模型列表页面从一个db切换到另一个db:
class MultiDBListFilter(admin.SimpleListFilter):
title = 'database'
parameter_name = 'db'
def lookups(self, request, model_admin):
return tuple((db, db) for db in ['default'])
def value(self):
return super(MultiDBListFilter, self).value() or 'default'
def queryset(self, request, queryset):
return queryset
def choices(self, cl):
choices = super(MultiDBListFilter, self).choices(cl)
choices.next() # Skip `All` choice.
for choice in choices:
yield choice
class MyModelAdmin(admin.ModelAdmin):
model = MyModel
list_filter = (MultiDBListFilter, )
def get_queryset(self, request):
db = request.GET.get('db', 'default')
return super(MyModelAdmin, self).get_queryset(request).using(db)
答案 1 :(得分:1)
@ Zack4我现在的代码几乎与你完全相同,但我的工作正常。
我看到的一个值得怀疑的事情是---虽然它会在1.7中被弃用,但我记得曾读过---在1.6.5中,我使用它仍然需要包括在url config中跟随:
admin.autodiscover()
当我省略时,我收到通知,表示我无权更改任何内容......不是问题中发现的问题,但可能正在做其他事情以避免这个问题并留下你的问题有
什么是" core.admin"在你的网址配置?根据我尝试时收到的错误消息,没有该名称的Django模块。是"核心"项目根目录的名称?也许与Django使用" core"这个词存在冲突。
最后,在我努力学习Django文档中的多个数据库时,我发现在setup.py中DATABASES中的第一个数据库有一个特殊的意义---如果你不使用数据库路由器(你和我不是)。
我给我的第一个数据库命名" subscriber"但在settings.py中它是:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': os.path.join(BASE_DIR, 'subscriber.db'),
....
现在,如果我尝试更改"默认"到"订户" Django反对并说我必须有一个"默认"数据库。我已经了解到,虽然与核心开发人员争论文档的票证,但是因为默认是接收auth模型的东西和其他管理相关的模型。
也就是说,如果您" python manage.py dbshell --database = default",然后键入" .tables",您不仅应该看到本地的表(或者也许默认是你的情况下的服务器),但也有各种身份验证和管理员的东西(键入" .quit"退出。)
现在如果对其他数据库执行相同操作会发生什么情况--database = server(如果那是“settings.py”中其他数据库的DATABASES键)?我第一次设置我的两个数据库时,我只是运行了syncdb,但是将auth和adminstrative模型放在两个数据库中。我只是从第二个数据库中删除了那些模型。
最后,它闻起来像一个简单的URL路由问题。您是否有机会为了这篇文章的出现而简化您的网址,在此过程中更改它们?你展示的东西看起来是正确的。