I am using a database router hence i have two databases for my application. One database for default django data and the other one.
In my admin i have override the save_model
function in order to save the created_by
variable, but i am unable to do this.
Cannot assign "<User: testuser>": the current database router prevents this relation.
database router:
from django.conf import settings
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
"""Point all read operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
"""Point all write operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
return None
def allow_relation(self, obj1, obj2, **hints):
"""Allow any relation between apps that use the same database."""
db_obj1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
db_obj2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
else:
return False
return None
def allow_syncdb(self, db, model):
"""Make sure that apps only appear in the related database."""
if model._meta.app_label in ['south']:
return True;
elif db in settings.DATABASE_APPS_MAPPING.values():
return settings.DATABASE_APPS_MAPPING.get(model._meta.app_label) == db
elif settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return False
return None
admin:
class SomeEntityAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
if not obj.created_by:
obj.created_by = user
obj.save()
I have even tried to define a different database by using save(using='thedb')
but that does not work either. Is my database router wrong?
The problem you are encountering arises from the difficulty of storing relations between objects that are stored in two distinct databases. In your example, you stated that you have created one database to store all Django contributed objects, which includes User objects created by the auth app. Meanwhile, the second model's objects will be stored in a distinct and entirely separate database. When you attempt to create a relationship between the new object stored in one database and the User object, you are attempting cross-database relations.
Cross-database relations are a difficult problem which has not been solved yet when using multiple databases in Django. If you would like more information about this issue, the Django documentation has a brief note about this problem (copied below for clarity).
Django doesn’t currently provide any support for foreign key or many-to-many relationships spanning multiple databases. If you have used a router to partition models to different databases, any foreign key and many-to-many relationships defined by those models must be internal to a single database.
This is because of referential integrity. In order to maintain a relationship between two objects, Django needs to know that the primary key of the related object is valid. If the primary key is stored on a separate database, it’s not possible to easily evaluate the validity of a primary key.
If you’re using Postgres, Oracle, or MySQL with InnoDB, this is enforced at the database integrity level – database level key constraints prevent the creation of relations that can’t be validated.
However, if you’re using SQLite or MySQL with MyISAM tables, there is no enforced referential integrity; as a result, you may be able to ‘fake’ cross database foreign keys. However, this configuration is not officially supported by Django.
If you want to stick with multiple dbs (with relations), all you need to do is implement a allow_relations method in your router that returns True when you are accessing the relation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With