【问题标题】:Using multiple Django admin sites for multiple databases为多个数据库使用多个 Django 管理站点
【发布时间】:2013-07-31 21:50:27
【问题描述】:

我需要在 Django Admin 中管理多个数据库。我的两个名为“本地”和“服务器”的数据库在设置文件中定义。由于 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/ URL 访问管理面板,但是内容是相同的:管理面板使用的是“本地”数据库,而不管我访问的是哪个管理面板。 Django怎么不区分这两者?

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    您可以覆盖 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)
    

    【讨论】:

      【解决方案2】:

      @Zack4 我现在的代码和你几乎一模一样,但我的工作正常。

      我看到的一个有问题的事情是——虽然它会在 1.7 中被弃用,但我记得我在 1.6.5 中读过——我正在使用它仍然需要在 url 配置中包含以下内容:

      admin.autodiscover()
      

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

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

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-25
        • 2017-02-10
        • 2012-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-14
        相关资源
        最近更新 更多