django.db.utils.DatabaseError:无法在MultiDB

时间:2018-01-18 08:25:42

标签: mysql django django-migrations django-database

我正在尝试将我的应用名称通知迁移到不同的数据库(名称是通知中心)但是在外键约束中出错,我知道Django在多个数据库中的限制,但两种模型(即notification_template,gateway_status)将在同一个数据库中迁移,请详细说明。我还将此路由器添加到settings.py

  

dbrouter.py:

class NotificationRouter(object):
    """
    A router to control all database operations on models in the
    auth application.
    """
    def db_for_read(self, model, **hints):
        """
        Attempts to read auth models go to auth_db.
        """
        if model._meta.app_label == 'notifications':
            return 'notificationcenter'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth models go to auth_db.
        """
        if model._meta.app_label == 'notifications':
            return 'notificationcenter'
        return None

    # def allow_relation(self, obj1, obj2, **hints):
    #     """
    #     Allow relations if a model in the auth app is involved.
    #     """
    #     if obj1._meta.app_label == 'auth' or \
    #        obj2._meta.app_label == 'auth':
    #        return True
    #     return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth app only appears in the 'auth_db'
        database.
        """
        if app_label == 'notifications':
            return db == 'notificationcenter'
        else:
            return False
        # elif db == 'default':
        #     # Ensure that all other apps don't get migrated on the example_db database.
        #     return False
        # return None
class CrossDbForeignKey(ForeignKey):
    def validate(self, value, model_instance):
        if self.rel.parent_link:
            return
        super(ForeignKey, self).validate(value, model_instance)
        if value is None:
            return

    # Here is the trick, get db relating to fk, not to root model
    using = router.db_for_read(self.rel.to, instance=model_instance)

    qs = self.rel.to._default_manager.using(using).filter(
            **{self.rel.field_name: value}
         )
    qs = qs.complex_filter(self.rel.limit_choices_to)
    if not qs.exists():
        raise exceptions.ValidationError(self.error_messages['invalid'] % {
            'model': self.rel.to._meta.verbose_name, 'pk': value})
  

Models.py:

from .dbrouter import CrossDbForeignKey
    class NotificationDBBaseModel(models.Model):
        created_on = models.DateTimeField('date created', blank=True, null=True, default=datetime.datetime.now)
        modified_on = models.DateTimeField('date modified', blank=True, null=True, default=datetime.datetime.now)
        created_by = CrossDbForeignKey(User, related_name="+", blank=True, null=True, default=get_current_user)
        modified_by = CrossDbForeignKey(User, blank=True, null=True)
        is_deleted = models.BooleanField('deleted', default=False)


    def save(self, *args, **kwargs):
        self.modified_by = get_current_user()
        self.modified_on = datetime.datetime.now()
        super(NotificationDBBaseModel, self).save(*args, **kwargs)

    class Meta:
        # app_label = 'notifications'
        abstract = True

class notification_template(NotificationDBBaseModel):
    message = models.TextField('message', blank=True, null=True,)
    subject = models.CharField('send to', max_length=150)
    via = models.CharField('via', max_length=5, blank=True, null=True,
                           choices=(('email', 'email'), ('sms', 'sms'), ('push', 'push')))

    class Meta:
        db_table = "notification_template"
        verbose_name = 'Notification Template'
        verbose_name_plural = 'Notification Templates'


class gateway_status(NotificationDBBaseModel):
    template = models.ForeignKey('notification_template')
    to = models.CharField('send to', max_length=1000)
    status = models.IntegerField('status', default=0)

    class Meta:
        db_table = "gateway_status"
        verbose_name = 'Gateway Status'
        verbose_name_plural = 'Gateway Statuses'
  

命令:

python manage.py makemigrations notifications
python manage.py migrate notifications --database=notificationcenter
  

错误:

    File "/Users/shashank/shashankenv/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 111, in execute
    cursor.execute(sql, params)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/django/base.py", line 227, in execute
    return self._execute_wrapper(self.cursor.execute, query, new_args)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/django/base.py", line 195, in _execute_wrapper
    utils.DatabaseError(err.msg), sys.exc_info()[2])
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/django/utils/six.py", line 658, in reraise
    raise value.with_traceback(tb)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/django/base.py", line 177, in _execute_wrapper
    return method(query, args)
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/cursor.py", line 559, in execute
    self._handle_result(self._connection.cmd_query(stmt))
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/connection.py", line 494, in cmd_query
    result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
  File "/Users/shashank/shashankenv/lib/python3.5/site-packages/mysql/connector/connection.py", line 396, in _handle_result
    raise errors.get_exception(packet)
django.db.utils.DatabaseError: Cannot add foreign key constraint

0 个答案:

没有答案