为多个数据库使用多个Django管理站点

时间:2013-07-31 21:50:27

标签: django django-admin

我需要在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不歧视这两个?

2 个答案:

答案 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 dbshel​​l --database = default",然后键入" .tables",您不仅应该看到本地的表(或者也许默认是你的情况下的服务器),但也有各种身份验证和管理员的东西(键入" .quit"退出。)

现在如果对其他数据库执行相同操作会发生什么情况--database = server(如果那是“settings.py”中其他数据库的DATABASES键)?我第一次设置我的两个数据库时,我只是运行了syncdb,但是将auth和adminstrative模型放在两个数据库中。我只是从第二个数据库中删除了那些模型。

最后,它闻起来像一个简单的URL路由问题。您是否有机会为了这篇文章的出现而简化您的网址,在此过程中更改它们?你展示的东西看起来是正确的。