Hi David

Your router isn't configured correctly. This applies to all the
allow_foo() methods, but see allow_migrate [1] as an example:

  Determine if the migration operation is allowed to run on the
database with alias db. Return True if the operation should run, False
if it shouldn’t run, or None if the router has no opinion.

Your routers *should* be having an opinion about whether that
app/model can be migrated on a specific database! For instance, you
say "the last app" should stay only on validations, but what your
ValidationRouter says is "If the app label is called fourth_model, run
migrations on this database", but it never checks what the database
is.

For ValidationRouter.allow_migrate you probably want something like this:

  def allow_migrate(self, ...):
      if app_label == "fourth_model":
          return db == "validations"
      elif db == "validations":
          return False

EG:
* if the app label is an app that should be in the validations DB,
allow migrate when the db is the validations DB
* if it isn't and the DB is the validations DB, don't allow migrations to it
* if neither of those things, this router doesn't care.

Similarly, for allow_relations() you should be returning False when
the models should not be related.

Incidentally, all python functions return None if the end of the
function is reached without an explicit return value, so you never
have to end your functions with an explicit "return None".

Cheers

Tom

[1] https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#allow_migrate
On Tue, Oct 30, 2018 at 10:09 AM David Lubomirov
<davidlubomi...@gmail.com> wrote:
>
> Hello,
>
> In my project I have 3 applications, and I'm trying to split them across 2 
> databases.
>
> More specifically 2 of the apps and Django "auth" application should work 
> with the first database,
> and the last application should remain in the second database.
>
> These are the DB settings:
>
> DATABASE_ROUTERS = [
>     '<PATH_TO_ROUTER>.PrimaryRouter',
>     '<PATH_TO_ROUTER>.ValidationRouter'
> ]
>
> DATABASES = {
>     'default': {},
>     'primary': {
>         'NAME': 'primary',
>         'ENGINE': 'django.db.backends.postgresql',
>         'USER': '<DB_USER>',
>         'PASSWORD': '<DB_PASS>',
>         'HOST': 'localhost',
>     },
>     'validations': {
>         'NAME': 'validations',
>         'ENGINE': 'django.db.backends.postgresql',
>         'USER': '<DB_USER>',
>         'PASSWORD': '<DB_PASS>',
>         'HOST': 'localhost',
>     }
> }
>
> Therefore these are the class routers:
>
> class PrimaryRouter:
>     """
>     Router to control all database operations for the following applications:
>     - first_model
>     - second_model
>     - auth
>     """
>     def db_for_read(self, model, **hints):
>         if model._meta.app_label == 'auth' or \
>             model._meta.app_label == 'first_model' or \
>             model._meta.app_label == 'second_model':
>
>             return 'primary'
>
>         return None
>
>     def db_for_write(self, model, **hints):
>         if model._meta.app_label == 'auth' or \
>             model._meta.app_label == 'first_model' or \
>             model._meta.app_label == 'second_model':
>
>             return 'primary'
>
>         return None
>
>     def allow_relation(self, first_object, second_object, **hints):
>         if first_object._meta.app_label == 'auth' or \
>             second_object._meta.app_label == 'auth':
>
>             return True
>
>         if first_object._meta.app_label == 'first_model' or \
>             second_object._meta.app_label == 'first_model':
>
>             return True
>
>         if first_object._meta.app_label == 'second_model' or \
>             second_object._meta.app_label == 'second_model':
>
>             return True
>
>         return None
>
>     def allow_migrate(self, db, app_label, model_name=None, **hints):
>         if app_label == 'auth' or \
>             app_label == 'first_model' or \
>             app_label == 'second_model':
>
>             return db == 'primary'
>
>         return None
>
>
> class ValidationRouter:
>     """
>     Router to control all database operations for the following applications:
>     - fourth_model
>     """
>     def db_for_read(self, model, **hints):
>         if model._meta.app_label == 'fourth_model':
>             return 'validations'
>
>         return None
>
>     def db_for_write(self, model, **hints):
>         if model._meta.app_label == 'fourth_model':
>             return 'validations'
>
>         return None
>
>     def allow_relation(self, first_object, second_object, **hints):
>         if first_object._meta.app_label == 'fourth_model' or \
>             second_object._meta.app_label == 'fourth_model':
>             return True
>
>         return None
>
>     def allow_migrate(self, db, app_label, model_name=None, **hints):
>         if app_label == 'fourth_model':
>             return True
>
>         return None
>
>
> When I run migration on the first database "primary", everything is working.
> But on the second database I'm getting the following exception:
>
>
> django.db.utils.ProgrammingError: relation "auth_user" does not exist
>
>
> The question - do I need to also specify the "auth" Django application in the 
> second DB router "validations",
> or there's something wrong with my setup ?
>
> According to Django docs for version 2.1, this kind of setup is working - 
> https://docs.djangoproject.com/en/2.1/topics/db/multi-db/ .
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to django-users+unsubscr...@googlegroups.com.
> To post to this group, send email to django-users@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/8eef7cfe-93ed-4322-ab84-09261e27f460%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CAFHbX1%2BOnVbc0%2BOGGvypGYcbDwum6azTwVg6fzgp%3D%3Dc79yqtzQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to