multi-db.txt 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. .. _topics-db-multi-db:
  2. ==================
  3. Multiple databases
  4. ==================
  5. .. versionadded:: 1.2
  6. This topic guide describes Django's support for interacting with
  7. multiple databases. Most of the rest of Django's documentation assumes
  8. you are interacting with a single database. If you want to interact
  9. with multiple databases, you'll need to take some additional steps.
  10. Defining your databases
  11. =======================
  12. The first step to using more than one database with Django is to tell
  13. Django about the database servers you'll be using. This is done using
  14. the :setting:`DATABASES` setting. This setting maps database aliases,
  15. which are a way to refer to a specific database throughout Django, to
  16. a dictionary of settings for that specific connection. The settings in
  17. the inner dictionaries are described fully in the :setting:`DATABASES`
  18. documentation.
  19. Databases can have any alias you choose. However, the alias
  20. ``default`` has special significance. Django uses the database with
  21. the alias of ``default`` when no other database has been selected. If
  22. you don't have a ``default`` database, you need to be careful to
  23. always specify the database that you want to use.
  24. The following is an example ``settings.py`` snippet defining two
  25. databases -- a default PostgreSQL database and a MySQL database called
  26. ``users``:
  27. .. code-block:: python
  28. DATABASES = {
  29. 'default': {
  30. 'NAME': 'app_data',
  31. 'ENGINE': 'django.db.backends.postgresql_psycopg2',
  32. 'USER': 'postgres_user',
  33. 'PASSWORD': 's3krit'
  34. },
  35. 'users': {
  36. 'NAME': 'user_data'
  37. 'ENGINE': 'django.db.backends.mysql',
  38. 'USER': 'mysql_user',
  39. 'PASSWORD': 'priv4te'
  40. }
  41. }
  42. If you attempt to access a database that you haven't defined in your
  43. :setting:`DATABASES` setting, Django will raise a
  44. ``django.db.utils.ConnectionDoesNotExist`` exception.
  45. Synchronizing your databases
  46. ============================
  47. The :djadmin:`syncdb` management command operates on one database at a
  48. time. By default, it operates on the ``default`` database, but by
  49. providing a :djadminopt:`--database` argument, you can tell syncdb to
  50. synchronize a different database. So, to synchronize all models onto
  51. all databases in our example, you would need to call::
  52. $ ./manage.py syncdb
  53. $ ./manage.py syncdb --database=users
  54. If you don't want every application to be synchronized onto a
  55. particular database. you can specify the :djadminopt:`--exclude`
  56. argument to :djadmin:`syncdb`. The :djadminopt:`--exclude` option lets
  57. you prevent a specific application or applications from being
  58. synchronized. For example, if you don't want the ``sales`` application
  59. to be in the ``users`` database, you could run::
  60. $ ./manage.py syncdb --database=users --exclude=sales
  61. Alternatively, if you want fine-grained control of synchronization,
  62. you can pipe all or part of the output of :djadmin:`sqlall` for a
  63. particular application directly into your database prompt, like this::
  64. $ ./manage.py sqlall sales | ./manage.py dbshell
  65. Using other management commands
  66. -------------------------------
  67. The other ``django-admin.py`` commands that interact with the database
  68. operate in the same way as :djadmin:`syncdb` -- they only ever operate
  69. on one database at a time, using :djadminopt:`--database` to control
  70. the database used.
  71. .. _topics-db-multi-db-routing:
  72. Automatic database routing
  73. ==========================
  74. The easiest way to use multiple databases is to set up a database
  75. routing scheme. The default routing scheme ensures that objects remain
  76. 'sticky' to their original database (i.e., an object retrieved from
  77. the ``foo`` database will be saved on the same database). However, you
  78. can implement more interesting behaviors by defining a different
  79. routing scheme.
  80. Database routers
  81. ----------------
  82. A database Router is a class that provides three methods:
  83. .. method:: db_for_read(model, **hints)
  84. Suggest the database that should be used for read operations for
  85. objects of type ``model``.
  86. If a database operation is able to provide any additional
  87. information that might assist in selecting a database, it will be
  88. provided in the ``hints`` dictionary. Details on valid hints are
  89. provided :ref:`below <topics-db-multi-db-hints>`.
  90. Returns None if there is no suggestion.
  91. .. method:: db_for_write(model, **hints)
  92. Suggest the database that should be used for writes of objects of
  93. type Model.
  94. If a database operation is able to provide any additional
  95. information that might assist in selecting a database, it will be
  96. provided in the ``hints`` dictionary. Details on valid hints are
  97. provided :ref:`below <topics-db-multi-db-hints>`.
  98. Returns None if there is no suggestion.
  99. .. method:: allow_relation(obj1, obj2, **hints)
  100. Return True if a relation between obj1 and obj2 should be
  101. allowed, False if the relation should be prevented, or None if
  102. the router has no opinion. This is purely a validation operation,
  103. used by foreign key and many to many operations to determine if a
  104. relation should be allowed between two objects.
  105. .. _topics-db-multi-db-hints:
  106. Hints
  107. ~~~~~
  108. The hints received by the database router can be used to decide which
  109. database should receive a given request.
  110. At present, the only hint that will be provided is ``instance``, an
  111. object instance that is related to the read or write operation that is
  112. underway. This might be the instance that is being saved, or it might
  113. be an instance that is being added in a many-to-many relation. In some
  114. cases, no instance hint will be provided at all. The router check for
  115. the existence of an instance hint, and determine if hat hint should be
  116. used to alter routing behavior.
  117. Using routers
  118. -------------
  119. Database routers are installed using the :setting:`DATABASE_ROUTERS`
  120. setting. This setting defines a list of class names, each specifying a
  121. router that should be used by the master router
  122. (``django.db.router``).
  123. The master router is used by Django's database operations to allocate
  124. database usage. Whenever a query needs to know which database to use,
  125. it calls the master router, providing a model and a hint (if
  126. available). Django then tries each router in turn until a database
  127. suggestion can be found. If no suggestion can be found, it tries the
  128. current ``_state.db`` of the hint instance. If a hint instance wasn't
  129. provided, or the instance doesn't currently have database state, the
  130. master router will allocate the ``default`` database.
  131. An example
  132. ----------
  133. .. admonition:: Example purposes only!
  134. This example is intended as a demonstration of how the router
  135. infrastructure can be used to alter database usage. It
  136. intentionally ignores some complex issues in order to
  137. demonstrate how routers are used.
  138. The approach of splitting ``contrib.auth`` onto a different
  139. database won't actually work on Postgres, Oracle, or MySQL with
  140. InnoDB tables. ForeignKeys to a remote database won't work due as
  141. they introduce referential integrity problems. If you're using
  142. SQLite or MySQL with MyISAM tables, there is no referential
  143. integrity checking, so you will be able to define cross-database
  144. foreign keys.
  145. The master/slave configuration described is also flawed -- it
  146. doesn't provide any solution for handling replication lag (i.e.,
  147. query inconsistencies introduced because of the time taken for a
  148. write to propagate to the slaves). It also doesn't consider the
  149. interaction of transactions with the database utiliztion strategy.
  150. So - what does this mean in practice? Say you want ``contrib.auth`` to
  151. exist on the 'credentials' database, and you want all other models in a
  152. master/slave relationship between the databses 'master', 'slave1' and
  153. 'slave2'. To implement this, you would need 2 routers::
  154. class AuthRouter(object):
  155. """A router to control all database operations on models in
  156. the contrib.auth application"""
  157. def db_for_read(self, model, **hints):
  158. "Point all operations on auth models to 'credentials'"
  159. if model._meta.app_label == 'auth':
  160. return 'credentials'
  161. return None
  162. def db_for_write(self, model, **hints):
  163. "Point all operations on auth models to 'credentials'"
  164. if model._meta.app_label == 'auth':
  165. return 'credentials'
  166. return None
  167. def allow_relation(self, obj1, obj2, **hints):
  168. "Allow any relation if a model in Auth is involved"
  169. if obj1._meta.app_label == 'auth' or obj2._meta.app_label == 'auth':
  170. return True
  171. return None
  172. class MasterSlaveRouter(object):
  173. """A router that sets up a simple master/slave configuration"""
  174. def db_for_read(self, model, **hints):
  175. "Point all read operations to a random slave"
  176. return random.choice(['slave1','slave2'])
  177. def db_for_write(self, model, **hints):
  178. "Point all write operations to the master"
  179. return 'master'
  180. def allow_relation(self, obj1, obj2, **hints):
  181. "Allow any relation between two objects in the db pool"
  182. db_list = ('master','slave1','slave2')
  183. if obj1 in db_list and obj2 in db_list:
  184. return True
  185. return None
  186. Then, in your settings file, add the following (substituting ``path.to.`` with
  187. the actual python path to the module where you define the routers)::
  188. DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.MasterSlaveRouter']
  189. With this setup installed, lets run some Django code::
  190. >>> # This retrieval will be performed on the 'credentials' database
  191. >>> fred = User.objects.get(username='fred')
  192. >>> fred.first_name = 'Frederick'
  193. >>> # This save will also be directed to 'credentials'
  194. >>> fred.save()
  195. >>> # These retrieval will be randomly allocated to a slave database
  196. >>> dna = Person.objects.get(name='Douglas Adams')
  197. >>> # A new object has no database allocation when created
  198. >>> mh = Book(title='Mostly Harmless')
  199. >>> # This assignment will consult the router, and set mh onto
  200. >>> # the same database as the author object
  201. >>> mh.author = dna
  202. >>> # This save will force the 'mh' instance onto the master database...
  203. >>> mh.save()
  204. >>> # ... but if we re-retrieve the object, it will come back on a slave
  205. >>> mh = Book.objects.get(title='Mostly Harmless')
  206. Manually selecting a database
  207. =============================
  208. Django also provides an API that allows you to maintain complete control
  209. over database usage in your code. A manually specified database allocation
  210. will take priority over a database allocated by a router.
  211. Manually selecting a database for a ``QuerySet``
  212. ------------------------------------------------
  213. You can select the database for a ``QuerySet`` at any point in the
  214. ``QuerySet`` "chain." Just call ``using()`` on the ``QuerySet`` to get
  215. another ``QuerySet`` that uses the specified database.
  216. ``using()`` takes a single argument: the alias of the database on
  217. which you want to run the query. For example::
  218. >>> # This will run on the 'default' database.
  219. >>> Author.objects.all()
  220. >>> # So will this.
  221. >>> Author.objects.using('default').all()
  222. >>> # This will run on the 'other' database.
  223. >>> Author.objects.using('other').all()
  224. Selecting a database for ``save()``
  225. -----------------------------------
  226. Use the ``using`` keyword to ``Model.save()`` to specify to which
  227. database the data should be saved.
  228. For example, to save an object to the ``legacy_users`` database, you'd
  229. use this::
  230. >>> my_object.save(using='legacy_users')
  231. If you don't specify ``using``, the ``save()`` method will save into
  232. the default database allocated by the routers.
  233. Moving an object from one database to another
  234. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  235. If you've saved an instance to one database, it might be tempting to
  236. use ``save(using=...)`` as a way to migrate the instance to a new
  237. database. However, if you don't take appropriate steps, this could
  238. have some unexpected consequences.
  239. Consider the following example::
  240. >>> p = Person(name='Fred')
  241. >>> p.save(using='first') # (statement 1)
  242. >>> p.save(using='second') # (statement 2)
  243. In statement 1, a new ``Person`` object is saved to the ``first``
  244. database. At this time, ``p`` doesn't have a primary key, so Django
  245. issues a SQL ``INSERT`` statement. This creates a primary key, and
  246. Django assigns that primary key to ``p``.
  247. When the save occurs in statement 2, ``p`` already has a primary key
  248. value, and Django will attempt to use that primary key on the new
  249. database. If the primary key value isn't in use in the ``second``
  250. database, then you won't have any problems -- the object will be
  251. copied to the new database.
  252. However, if the primary key of ``p`` is already in use on the
  253. ``second`` database, the existing object in the ``second`` database
  254. will be overridden when ``p`` is saved.
  255. You can avoid this in two ways. First, you can clear the primary key
  256. of the instance. If an object has no primary key, Django will treat it
  257. as a new object, avoiding any loss of data on the ``second``
  258. database::
  259. >>> p = Person(name='Fred')
  260. >>> p.save(using='first')
  261. >>> p.pk = None # Clear the primary key.
  262. >>> p.save(using='second') # Write a completely new object.
  263. The second option is to use the ``force_insert`` option to ``save()``
  264. to ensure that Django does a SQL ``INSERT``::
  265. >>> p = Person(name='Fred')
  266. >>> p.save(using='first')
  267. >>> p.save(using='second', force_insert=True)
  268. This will ensure that the person named ``Fred`` will have the same
  269. primary key on both databases. If that primary key is already in use
  270. when you try to save onto the ``second`` database, an error will be
  271. raised.
  272. Selecting a database to delete from
  273. -----------------------------------
  274. By default, a call to delete an existing object will be executed on
  275. the same database that was used to retrieve the object in the first
  276. place::
  277. >>> u = User.objects.using('legacy_users').get(username='fred')
  278. >>> u.delete() # will delete from the `legacy_users` database
  279. To specify the database from which a model will be deleted, pass a
  280. ``using`` keyword argument to the ``Model.delete()`` method. This
  281. argument works just like the ``using`` keyword argument to ``save()``.
  282. For example, if you're migrating a user from the ``legacy_users``
  283. database to the ``new_users`` database, you might use these commands::
  284. >>> user_obj.save(using='new_users')
  285. >>> user_obj.delete(using='legacy_users')
  286. Using managers with multiple databases
  287. --------------------------------------
  288. Use the ``db_manager()`` method on managers to give managers access to
  289. a non-default database.
  290. For example, say you have a custom manager method that touches the
  291. database -- ``User.objects.create_user()``. Because ``create_user()``
  292. is a manager method, not a ``QuerySet`` method, you can't do
  293. ``User.objects.using('new_users').create_user()``. (The
  294. ``create_user()`` method is only available on ``User.objects``, the
  295. manager, not on ``QuerySet`` objects derived from the manager.) The
  296. solution is to use ``db_manager()``, like this::
  297. User.objects.db_manager('new_users').create_user(...)
  298. ``db_manager()`` returns a copy of the manager bound to the database you specify.
  299. Using ``get_query_set()`` with multiple databases
  300. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  301. If you're overriding ``get_query_set()`` on your manager, be sure to
  302. either call the method on the parent (using ``super()``) or do the
  303. appropriate handling of the ``_db`` attribute on the manager (a string
  304. containing the name of the database to use).
  305. For example, if you want to return a custom ``QuerySet`` class from
  306. the ``get_query_set`` method, you could do this::
  307. class MyManager(models.Manager):
  308. def get_query_set(self):
  309. qs = CustomQuerySet(self.model)
  310. if self._db is not None:
  311. qs = qs.using(self._db)
  312. return qs
  313. Exposing multiple databases in Django's admin interface
  314. =======================================================
  315. Django's admin doesn't have any explicit support for multiple
  316. databases. If you want to provide an admin interface for a model on a
  317. database other than that that specified by your router chain, you'll
  318. need to write custom :class:`~django.contrib.admin.ModelAdmin` classes
  319. that will direct the admin to use a specific database for content.
  320. ``ModelAdmin`` objects have four methods that require customization for
  321. multiple-database support::
  322. class MultiDBModelAdmin(admin.ModelAdmin):
  323. # A handy constant for the name of the alternate database.
  324. using = 'other'
  325. def save_model(self, request, obj, form, change):
  326. # Tell Django to save objects to the 'other' database.
  327. obj.save(using=self.using)
  328. def queryset(self, request):
  329. # Tell Django to look for objects on the 'other' database.
  330. return super(MultiDBModelAdmin, self).queryset(request).using(self.using)
  331. def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
  332. # Tell Django to populate ForeignKey widgets using a query
  333. # on the 'other' database.
  334. return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
  335. def formfield_for_manytomany(self, db_field, request=None, **kwargs):
  336. # Tell Django to populate ManyToMany widgets using a query
  337. # on the 'other' database.
  338. return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
  339. The implementation provided here implements a multi-database strategy
  340. where all objects of a given type are stored on a specific database
  341. (e.g., all ``User`` objects are in the ``other`` database). If your
  342. usage of multiple databases is more complex, your ``ModelAdmin`` will
  343. need to reflect that strategy.
  344. Inlines can be handled in a similar fashion. They require three customized methods::
  345. class MultiDBTabularInline(admin.TabularInline):
  346. using = 'other'
  347. def queryset(self, request):
  348. # Tell Django to look for inline objects on the 'other' database.
  349. return super(MultiDBTabularInline, self).queryset(request).using(self.using)
  350. def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
  351. # Tell Django to populate ForeignKey widgets using a query
  352. # on the 'other' database.
  353. return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs)
  354. def formfield_for_manytomany(self, db_field, request=None, **kwargs):
  355. # Tell Django to populate ManyToMany widgets using a query
  356. # on the 'other' database.
  357. return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
  358. Once you've written your model admin definitions, they can be
  359. registered with any ``Admin`` instance::
  360. from django.contrib import admin
  361. # Specialize the multi-db admin objects for use with specific models.
  362. class BookInline(MultiDBTabularInline):
  363. model = Book
  364. class PublisherAdmin(MultiDBModelAdmin):
  365. inlines = [BookInline]
  366. admin.site.register
  367. admin.site.register(Author, MultiDBModelAdmin)
  368. admin.site.register(Publisher, PublisherAdmin)
  369. othersite = admin.Site('othersite')
  370. othersite.register(Publisher, MultiDBModelAdmin)
  371. This example sets up two admin sites. On the first site, the
  372. ``Author`` and ``Publisher`` objects are exposed; ``Publisher``
  373. objects have an tabular inline showing books published by that
  374. publisher. The second site exposes just publishers, without the
  375. inlines.