2

I need to manage multiple databases within Django Admin. My two databases named 'local' and 'server' are defined in the settings file. Since Django doesn't allow to add several times the same model with different ModelAdmin, I am creating two instances of admin.AdminSite.

Here is the code of the admin.py file:

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)

and here is the urls.py file:

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)),
            [...]
)

I can access the admin panel using both the admin/ and serveradmin/ URLs, however the content is the very same: the administration panel is using the 'local' database, regardless of the admin panel I access. How come Django doesn't discriminate the two?

4

2 回答 2

2

您可以覆盖 get_queryset 方法并使用过滤器来允许将管理员上的模型列表页面从一个 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)
于 2014-10-29T20:44:04.763 回答
1

@Zack4 我现在拥有与您几乎完全相同的代码,但我的工作。

我看到的一件值得怀疑的事情是——虽然它将在 1.7 中被弃用,但我记得在我正在使用的 1.6.5 中阅读过——它仍然需要在 url 配置中包含以下内容:

admin.autodiscover()

当我省略时,我收到通知说我无权更改任何内容……不是问题中确定的问题,而是可能正在做其他事情来避免该问题并留下您所拥有的问题。

您的 url 配置中的“core.admin”是什么?根据我尝试时收到的错误消息,没有该名称的 Django 模块。“核心”是您的项目根目录的名称吗?也许与 Django 对“核心”一词的使用存在冲突。

最后,在我努力学习 Django 文档中的多个数据库的过程中,我发现 DATABASES 中的第一个数据库在 setting.py 中具有特殊意义——如果你不使用数据库路由器(你和我不是)。

我将我的第一个数据库命名为“订阅者”,但在 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 对象并说我必须有一个“默认”数据库。我在与核心开发人员争论文档时了解到,这是因为默认情况下可以接收身份验证模型内容和其他与管理员相关的模型。

也就是说,如果你“python manage.py dbshel​​l --database=default”,然后输入“.tables”,你不仅应该看到你的本地表(或者在你的情况下默认是服务器),而且还应该看到各种身份验证和管理的东西。(键入“.quit”退出。)

现在如果你对另一个数据库做同样的事情会发生什么,--database=server(如果这是settings.py中另一个数据库的DATABASES键)?第一次设置我的两个数据库时,我只是简单地运行了 syncdb,但这会将 auth 和 adminstrative 模型放在两个数据库中。我只是从我的第二个数据库中删除了这些模型。

最后,它闻起来像是一个简单的 url 路由问题。您是否为了这篇文章的外观而简化了您的网址,并在此过程中更改了它们?你展示的看起来是对的。

于 2014-07-26T11:35:43.573 回答