0

I'm encountering a ValueError in my Django application when trying to save a User object with a related UserRoleAssociation in the admin interface. The error occurs in a multi-database setup where both the UserRoleAssociation and Role models are intended to use the members database. The error message is:

ValueError: Cannot assign "<Role: Role object (67c43a2e-c4e7-4846-bd31-700bf5d35e82)>": the current database router prevents this relation.

I have a Django project with two databases: default and members. The User, UserRoleAssociation, and Role models are all configured to use the members database via admin classes. The error occurs when saving a User object with an inline UserRoleAssociation in the Django admin.

Models

# models.py
class Role(models.Model):
 id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 role_name = models.CharField(max_length=255, unique=True)
 class Meta:
 db_table = "roles"
class UserRoleAssociation(models.Model):
 user = models.ForeignKey("User", on_delete=models.CASCADE)
 role = models.ForeignKey("Role", on_delete=models.CASCADE)
 def __str__(self):
 return f"{self.role.role_name}"
 
 class Meta:
 unique_together = ["user", "role"]
 db_table = "user_role_association"
class User(models.Model):
 phone_number = models.CharField(max_length=15)
 is_premium = models.BooleanField(default=False)
 roles = models.ManyToManyField("Role", through=UserRoleAssociation, related_name="users")
 class Meta:
 db_table = "users"
 app_label = "members"
 base_manager_name = 'objects'
 default_manager_name = 'objects'

Admin Configuration I use a custom MultiDBModelAdmin and MultiDBTabularInline to enforce the members database:

# admin.py
class MultiDBModelAdmin(admin.ModelAdmin):
 using = "members"
 def save_model(self, request, obj, form, change):
 obj.save(using=self.using)
 def delete_model(self, request, obj):
 obj._state.db = self.using
 obj.delete(using=self.using)
 
 def delete_queryset(self, request, queryset):
 queryset.using(self.using).delete()
 def get_queryset(self, request):
 return super().get_queryset(request).using(self.using)
 def formfield_for_foreignkey(self, db_field, request, **kwargs):
 return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)
 def formfield_for_manytomany(self, db_field, request, **kwargs):
 return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
 
 def _save_related(self, request, form, formsets, change):
 """Ensure related objects are saved in the correct database."""
 for formset in formsets:
 formset.instance._state.db = self.using # Force the database
 super()._save_related(request, form, formsets, change)
class MultiDBTabularInline(admin.StackedInline):
 using = "members"
 def get_queryset(self, request):
 return super().get_queryset(request).using(self.using)
 def formfield_for_manytomany(self, db_field, request, **kwargs):
= # Tell Django to populate ManyToMany widgets using a query
 # on the 'members' database.
 return super().formfield_for_manytomany(
 db_field, request, using=self.using, **kwargs
 )
class UserRoleAssociationInline(MultiDBTabularInline):
 model = UserRoleAssociation
 extra = 1
@admin.register(User)
class MemberAdmin(MultiDBModelAdmin):
 list_display = ["id"]
 inlines = [UserRoleAssociationInline]

The error occurs when saving a User object with a UserRoleAssociation inline in the admin interface.

asked Jun 16, 2025 at 4:46

1 Answer 1

0

Make sure your "DatabaseRouter" allows relation
#routers.py

class MembersRouter:
 def db_for_read(self, model, **hints):
 if model._meta.app_label == "members":
 return "members"
 return None
 def db_for_write(self, model, **hints):
 if model._meta.app_label == "members":
 return "members"
 return None
 def allow_relation(self, obj1, obj2, **hints):
 if obj1._meta.app_label == "members" and obj2._meta.app_label == "members":
 return True
 return None
 def allow_migrate(self, db, app_label, model_name=None, **hints):
 if app_label == "members":
 return db == "members"
 return None

**
Also check you have to add this into your settings.py**
DATABASE_ROUTERS = ['path.to.routers.MembersRouter']

Now, Force correct DB to when saving the inline model "UserRoleSelection"

def _save_related(self, request, form, formsets, change):
 for formset in formsets:
 instances = formset.save(commit=False)
 for obj in instances:
 obj._state.db = self.using
 obj.save(using=self.using)
 formset.save_m2m()
answered Jun 20, 2025 at 10:25
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.