Opened 3 years ago

Closed 16 months ago

#18360 closed Cleanup/optimization (duplicate)

Database router example improvement

Reported by: sbaechler Owned by: nobody
Component: Documentation Version: 1.4
Severity: Normal Keywords: multiple database
Cc: simon@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In your example for a database router on https://docs.djangoproject.com/en/1.4/topics/db/multi-db/ there is one problem:
If you have several app accessing the 'other' database and multiple routers, the syncdb will not work for any app but the first one.

Currently it is:

class MyAppRouter(object):
    def allow_syncdb(self, db, model):
        "Make sure the myapp app only appears on the 'other' db"
        if db == 'other':
            return model._meta.app_label == 'myapp'
        elif model._meta.app_label == 'myapp':
            return False
        return None

If the database is 'other' and the app_label is not 'myapp' the router returns False and syncdb won't work for all other routers for this db.

A better example would be:

    def allow_syncdb(self, db, model):
        if db == 'other' and model._meta.app_label == 'myapp':
            return True
        elif model._meta.app_label == 'myapp':
            return False
        return None

Change History (6)

comment:1 Changed 3 years ago by sbaechler

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Scratch that example. This would cause all models to sync on the 'other' db as well.

So there can only be one router per db then (should be noted in the docs):

     def allow_syncdb(self, db, model):
        "Make sure the myapp app only appears on the 'other' db"
        if db == 'other':
            return model._meta.app_label in ['myapp', 'myotherapp']
        elif model._meta.app_label == 'myapp':
            return False
        return None
Version 0, edited 3 years ago by sbaechler (next)

comment:2 Changed 3 years ago by russellm

  • Resolution set to invalid
  • Status changed from new to closed

I'm not sure I understand your report here.

The example is a specific demonstration of what you would do if "you want myapp to exist on the other database, and you want all other models in a master/slave relationship between the databases master, slave1 and slave2"; This is exactly what the provided router implements. MyAppRouter.allow_syncdb returns:

  • True if you're synchronising the other database, and it is asked about a model from myapp
  • False if you're synchronising the other database, and it is asked about a model that *isn't* from myapp
  • False if you're synchronizing a database that isn't 'other', and it is asked about a model from myapp
  • Don't care otherwise.

Your code starts to introduce "myotherapp" -- i.e., an app that isn't "myapp" -- which, by the original problem definition, should *not* be synchronised onto 'other'. That doesn't mean that myotherapp can't *access* other -- just that the models from myotherapp won't be synchronised onto other. myotherapp can still access myapp.MyModel without any problem.

You said: "If you have several app accessing the 'other' database". This is in direct conflict with the stated problem that MyAppRouter is trying to solve.

You then clarified with "there can only be one router per db". I have no idea why you are making this assertion -- the example in the docs clearly uses 2 routers, and works fine AFAICT.

Marking invalid; if I've misunderstood your report, feel free to reopen with more details. However, keep in mind that all we're trying to do here is provide an indicative problem, not provide a solution to every problem.

comment:3 Changed 3 years ago by sbaechler

  • Cc simon@… added
  • Resolution invalid deleted
  • Status changed from closed to reopened

Hi Russel

I agree, my example was unclear and my usecase maybe too specific. Although having several apps that all need access to the 'other' database should not be too uncommon.

Anyway, this does not change the fact that I think the multi-db docs is not deep enough for developers to fully understand the concept of database routers. Here that particular example is the only example on how to use routers.

Let me explain: What guided me in the wrong direction was the naming of your example router class. Because it is named MyAppRouter it implied to me that you are going to need a router for every app. Which turned out to be wrong. Because if you do that, you won't get syncdb or dumpdata for every app that is not in the first router in the list. So if it would have been named 'OtherDbRouter' I would have instinctively used only one router for all apps that use the 'other' db, which turned out to be the correct solution.

comment:4 Changed 3 years ago by aaugustin

  • Triage Stage changed from Unreviewed to Accepted

I agree that the class name is misleading.

comment:5 Changed 2 years ago by aaugustin

  • Status changed from reopened to new

comment:6 Changed 16 months ago by claudep

  • Resolution set to duplicate
  • Status changed from new to closed

Router docs have been updated as part of fixing ticket #18657. Reopen with some concrete proposal if you find the docs still lacking.

Note: See TracTickets for help on using tickets.
Back to Top