【问题标题】:Django Multi-App Database Router not workingDjango多应用数据库路由器不工作
【发布时间】:2016-10-12 15:40:36
【问题描述】:

我正在使用 Django 1.10 和 Python 2.7 做一个项目。

我已经阅读并尝试根据this page实现数据库路由。我还阅读了许多不同的教程和其他 stackoverflow 问题。但是,我似乎无法让它工作。

这是我的场景:

我需要默认数据库上的所有分析、身份验证和管理应用模型。然后取消应用在一个单独的数据库上,而 driveractivity 应用在另一个单独的数据库上。

这是我正在使用的路由器:

from django.conf import settings


class AppRouter:
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'analytics':
            return 'default'

        elif model._meta.app_label == 'cancellation':
            return 'cancellations_db'

        elif model._meta.app_label == 'driveractivity':
            return 'driveractivity_db'

        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'analytics':
            return 'default'

        elif model._meta.app_label == 'cancellation':
            return 'cancellations_db'

        elif model._meta.app_label == 'driveractivity':
            return 'driveractivity_db'

        return None

    def allow_migrate(self, db, app_label, model=None, **hints):    
        if app_label == 'cancellation' and db == 'cancellations_db':
            return True

        if app_label == 'driveractivity' and db == 'driveractivity_db':
            return True

        if app_label in ('analytics', 'auth', 'admin', 'contenttypes', 'sessions', 'rest_framework') and db == 'default':
            return True

        return False

我的数据库设置如下(settings.py):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'NAME': 'analytics',
        'USER': 'root'
    },
    'driveractivity_db': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'NAME': 'driveractivity',
        'USER': 'root',
    },
    'cancellations_db': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'NAME': 'teke_cancellation',
        'USER': 'root'
    }
}

DATABASE_ROUTERS = ['analytics.AppRouter.AppRouter']

DB_Mapping = {
    "cancellation": "cancellations_db",
    "driveractivity": "driveractivity_db"
}

models.py - 取消

class Cancellation(models.Model):
    id = models.IntegerField(primary_key=True)
    user = models.EmailField(max_length=255,blank=False)
    time = models.DateField(blank=False)
        created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'


class PenaltyType(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255,blank=False)
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'


class Penalty(models.Model):
    id = models.IntegerField(primary_key=True)
    user = models.EmailField(max_length=255,blank=False)
    meted = models.BooleanField(default=False)
    penalty_type = models.ForeignKey(PenaltyType)
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'

models.py - driveractivity

class Activity(models.Model):
    email = models.EmailField(null=False)
    driver_name = models.CharField(max_length=30,null=False)
    vehicle_reg = models.CharField(max_length=30,null=False)
    status = models.CharField(max_length=15)
    desc = models.CharField(max_length=250)
    lng = models.FloatField()
    lat = models.FloatField()
    time = models.DateTimeField()
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'driveractivity'


class DistanceDetails(models.Model):
    email = models.EmailField(null=False)
    driver_name = models.CharField(max_length=30,null=False)
    vehicle_reg = models.CharField(max_length=30,null=False)
    new_lng = models.FloatField()
    new_lat = models.FloatField()
    last_state = models.CharField(max_length=15,null=False)
    last_lng = models.FloatField()
    last_lat = models.FloatField()
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'driveractivity'

已编辑 router.py

class AppRouter(object):
    def db_for_read(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')

    def db_for_write(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label in DB_Mapping.keys() or db in DB_Mapping.values():
            return True
        else:
            return None

是不是我做错了什么?

【问题讨论】:

    标签: python django


    【解决方案1】:

    检查这是否适合您:

    settings.py

    DB_Mapping = {
        "cancellation": "cancellation_db",
        "driveractivity": "driveractivity_db",
        ...
    }
    

    router.py

    from project.settings import DB_Mapping
    
    class MyRouter(object):
        def db_for_read(self, model, **hints):
            return DB_Mapping.get(model._meta.app_label, 'default')
    
        def db_for_write(self, model, **hints):
            return DB_Mapping.get(model._meta.app_label, 'default')
    

    我确实使用了类似的设置,我根据发出请求的用户组路由到不同的数据库用户。

    allow_migrate 也可以这样写,如果db == 'default'if model._meta.app_label in DB_Mapping.keys() or db in DB_Mapping.values(): return True else False

    【讨论】:

    • 这仍然会在默认数据库中创建模型。还是不知道为什么
    • 你能确保你的模型中有 app-label 吗?这是上面代码出错的唯一方法。我本质上是说如果没有找到映射则返回默认数据库,否则返回映射的数据库。
    • 我已经通过模型上的 Meta 类添加了 app_label,但它仍然不起作用。这些表仍然在默认数据库中创建。
    • 是否可以粘贴一些你的 settings.py、router.py 和 models.py 的 sn-ps 你需要通过设置来告诉 django 使用你的自定义路由器而不是默认路由器:DATABASE_ROUTERS = ('project.customRouter.myRouter', )
    • 我已编辑问题以包含请求的详细信息
    【解决方案2】:

    你的线路

    DATABASE_ROUTERS = ['analytics.AppRouter.AppRouter']
    

    可能需要改为:

    DATABASE_ROUTERS = ['analytics.router.AppRouter']
    
    

    【讨论】:

      猜你喜欢
      • 2011-12-24
      • 2012-03-28
      • 1970-01-01
      • 1970-01-01
      • 2017-06-16
      • 2012-10-03
      • 2018-04-05
      • 2017-10-16
      相关资源
      最近更新 更多