我正在尝试将我的应用名称通知迁移到不同的数据库(名称是通知中心)但是在外键约束中出错,我知道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