{"title":"Multiple databases","version":"3.2","locale":"ko","docname":"topics/db/multi-db","url":"/ko/3.2/topics/db/multi-db/","canonical":"https://djangodocs.dev/ko/3.2/topics/db/multi-db/","summary":"This topic guide describes Django’s support for interacting with multiple databases. Most of the rest of Django’s documentation assumes you are interacting with a…","html":"<h1>Multiple databases<a class=\"heading-anchor\" href=\"#multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This topic guide describes Django’s support for interacting with\nmultiple databases. Most of the rest of Django’s documentation assumes\nyou are interacting with a single database. If you want to interact\nwith multiple databases, you’ll need to take some additional steps.</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">더 보기</p>\n<p>See <a class=\"reference internal\" href=\"/ko/3.2/topics/testing/tools/#testing-multi-db\"><span class=\"std std-ref\">Multi-database support</span></a> for information about testing with multiple\ndatabases.</p>\n</aside>\n<section id=\"defining-your-databases\">\n<h2>데이터베이스 정의<a class=\"heading-anchor\" href=\"#defining-your-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The first step to using more than one database with Django is to tell\nDjango about the database servers you’ll be using. This is done using\nthe <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> setting. This setting maps database aliases,\nwhich are a way to refer to a specific database throughout Django, to\na dictionary of settings for that specific connection. The settings in\nthe inner dictionaries are described fully in the <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a>\ndocumentation.</p>\n<p>Databases can have any alias you choose. However, the alias\n<code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> has special significance. Django uses the database with\nthe alias of <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> when no other database has been selected.</p>\n<p>The following is an example <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> snippet defining two\ndatabases – a default PostgreSQL database and a MySQL database called\n<code class=\"docutils literal notranslate\"><span class=\"pre\">users</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;app_data&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.postgresql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;postgres_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;s3krit&#39;</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;users&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;user_data&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;priv4te&#39;</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>If the concept of a <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database doesn’t make sense in the context\nof your project, you need to be careful to always specify the database\nthat you want to use. Django requires that a <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database entry\nbe defined, but the parameters dictionary can be left blank if it will not be\nused. To do this, you must set up <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASE_ROUTERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE_ROUTERS</span></code></a> for all of your\napps’ models, including those in any contrib and third-party apps you’re using,\nso that no queries are routed to the default database. The following is an\nexample <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> snippet defining two non-default databases, with the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> entry intentionally left empty:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{},</span>\n    <span class=\"s1\">&#39;users&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;user_data&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;superS3cret&#39;</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;customers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;customer_data&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_cust&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;veryPriv@ate&#39;</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>If you attempt to access a database that you haven’t defined in your\n<a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> setting, Django will raise a\n<code class=\"docutils literal notranslate\"><span class=\"pre\">django.utils.connection.ConnectionDoesNotExist</span></code> exception.</p>\n</section>\n<section id=\"synchronizing-your-databases\">\n<span id=\"synchronizing-multiple-databases\"></span><h2>데이터베이스 연동<a class=\"heading-anchor\" href=\"#synchronizing-your-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> management command operates on one database at a\ntime. By default, it operates on the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database, but by\nproviding the <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#cmdoption-migrate-database\"><code class=\"xref std std-option docutils literal notranslate\"><span class=\"pre\">--database</span></code></a> option, you can tell it\nto synchronize a different database. So, to synchronize all models onto\nall databases in the first example above, you would need to call:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>$ ./manage.py migrate\n$ ./manage.py migrate --database=users\n</code></pre></div>\n<p>If you don’t want every application to be synchronized onto a\nparticular database, you can define a <a class=\"reference internal\" href=\"#topics-db-multi-db-routing\"><span class=\"std std-ref\">database\nrouter</span></a> that implements a policy\nconstraining the availability of particular models.</p>\n<p>If, as in the second example above, you’ve left the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database empty,\nyou must provide a database name each time you run <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a>. Omitting\nthe database name would raise an error. For the second example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>$ ./manage.py migrate --database=users\n$ ./manage.py migrate --database=customers\n</code></pre></div>\n<section id=\"using-other-management-commands\">\n<h3>다른 관리 명령어 사용하기<a class=\"heading-anchor\" href=\"#using-other-management-commands\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Most other <code class=\"docutils literal notranslate\"><span class=\"pre\">django-admin</span></code> commands that interact with the database operate in\nthe same way as <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> – they only ever operate on one database at\na time, using <code class=\"docutils literal notranslate\"><span class=\"pre\">--database</span></code> to control the database used.</p>\n<p>An exception to this rule is the <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code></a> command. It\nvalidates the migration history in the databases to catch problems with the\nexisting migration files (which could be caused by editing them) before\ncreating new migrations. By default, it checks only the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database,\nbut it consults the <a class=\"reference internal\" href=\"#allow_migrate\" title=\"allow_migrate\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">allow_migrate()</span></code></a> method of <a class=\"reference internal\" href=\"#topics-db-multi-db-routing\"><span class=\"std std-ref\">routers</span></a> if any are installed.</p>\n</section>\n</section>\n<section id=\"automatic-database-routing\">\n<span id=\"topics-db-multi-db-routing\"></span><h2>Automatic database routing<a class=\"heading-anchor\" href=\"#automatic-database-routing\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The easiest way to use multiple databases is to set up a database\nrouting scheme. The default routing scheme ensures that objects remain\n‘sticky’ to their original database (i.e., an object retrieved from\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></code> database will be saved on the same database). The default\nrouting scheme ensures that if a database isn’t specified, all queries\nfall back to the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database.</p>\n<p>You don’t have to do anything to activate the default routing scheme\n– it is provided ‘out of the box’ on every Django project. However,\nif you want to implement more interesting database allocation\nbehaviors, you can define and install your own database routers.</p>\n<section id=\"database-routers\">\n<h3>데이터베이스 라우터<a class=\"heading-anchor\" href=\"#database-routers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A database Router is a class that provides up to four methods:</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"db_for_read\">\n<span class=\"sig-name descname\"><span class=\"pre\">db_for_read</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">model</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">hints</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#db_for_read\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Suggest the database that should be used for read operations for\nobjects of type <code class=\"docutils literal notranslate\"><span class=\"pre\">model</span></code>.</p>\n<p>If a database operation is able to provide any additional\ninformation that might assist in selecting a database, it will be\nprovided in the <code class=\"docutils literal notranslate\"><span class=\"pre\">hints</span></code> dictionary. Details on valid hints are\nprovided <a class=\"reference internal\" href=\"#topics-db-multi-db-hints\"><span class=\"std std-ref\">below</span></a>.</p>\n<p>어떤 제안도 없으면 “None”을 반환합니다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"db_for_write\">\n<span class=\"sig-name descname\"><span class=\"pre\">db_for_write</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">model</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">hints</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#db_for_write\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Suggest the database that should be used for writes of objects of\ntype Model.</p>\n<p>If a database operation is able to provide any additional\ninformation that might assist in selecting a database, it will be\nprovided in the <code class=\"docutils literal notranslate\"><span class=\"pre\">hints</span></code> dictionary. Details on valid hints are\nprovided <a class=\"reference internal\" href=\"#topics-db-multi-db-hints\"><span class=\"std std-ref\">below</span></a>.</p>\n<p>어떤 제안도 없으면 “None”을 반환합니다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"allow_relation\">\n<span class=\"sig-name descname\"><span class=\"pre\">allow_relation</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj2</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">hints</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#allow_relation\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Return <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if a relation between <code class=\"docutils literal notranslate\"><span class=\"pre\">obj1</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">obj2</span></code> should be\nallowed, <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> if the relation should be prevented, or <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> if\nthe router has no opinion. This is purely a validation operation,\nused by foreign key and many to many operations to determine if a\nrelation should be allowed between two objects.</p>\n<p>If no router has an opinion (i.e. all routers return <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>), only\nrelations within the same database are allowed.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"allow_migrate\">\n<span class=\"sig-name descname\"><span class=\"pre\">allow_migrate</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">db</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">app_label</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">model_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">hints</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#allow_migrate\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Determine if the migration operation is allowed to run on the database with\nalias <code class=\"docutils literal notranslate\"><span class=\"pre\">db</span></code>. Return <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if the operation should run, <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> if it\nshouldn’t run, or <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> if the router has no opinion.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">app_label</span></code> positional argument is the label of the application\nbeing migrated.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">model_name</span></code> is set by most migration operations to the value of\n<code class=\"docutils literal notranslate\"><span class=\"pre\">model._meta.model_name</span></code> (the lowercased version of the model\n<code class=\"docutils literal notranslate\"><span class=\"pre\">__name__</span></code>) of the model being migrated. Its value is <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> for the\n<a class=\"reference internal\" href=\"/ko/3.2/ref/migration-operations/#django.db.migrations.operations.RunPython\" title=\"django.db.migrations.operations.RunPython\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunPython</span></code></a> and\n<a class=\"reference internal\" href=\"/ko/3.2/ref/migration-operations/#django.db.migrations.operations.RunSQL\" title=\"django.db.migrations.operations.RunSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RunSQL</span></code></a> operations unless they\nprovide it using hints.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">hints</span></code> are used by certain operations to communicate additional\ninformation to the router.</p>\n<p>When <code class=\"docutils literal notranslate\"><span class=\"pre\">model_name</span></code> is set, <code class=\"docutils literal notranslate\"><span class=\"pre\">hints</span></code> normally contains the model class\nunder the key <code class=\"docutils literal notranslate\"><span class=\"pre\">'model'</span></code>. Note that it may be a <a class=\"reference internal\" href=\"/ko/3.2/topics/migrations/#historical-models\"><span class=\"std std-ref\">historical model</span></a>, and thus not have any custom attributes, methods, or\nmanagers. You should only rely on <code class=\"docutils literal notranslate\"><span class=\"pre\">_meta</span></code>.</p>\n<p>This method can also be used to determine the availability of a model on a\ngiven database.</p>\n<p><a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code></a> always creates migrations for model changes, but\nif <code class=\"docutils literal notranslate\"><span class=\"pre\">allow_migrate()</span></code> returns <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>, any migration operations for the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">model_name</span></code> will be silently skipped when running <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> on\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">db</span></code>. Changing the behavior of <code class=\"docutils literal notranslate\"><span class=\"pre\">allow_migrate()</span></code> for models that\nalready have migrations may result in broken foreign keys, extra tables,\nor missing tables. When <a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code></a> verifies the migration\nhistory, it skips databases where no app is allowed to migrate.</p>\n</dd></dl>\n\n<p>A router doesn’t have to provide <em>all</em> these methods – it may omit one\nor more of them. If one of the methods is omitted, Django will skip\nthat router when performing the relevant check.</p>\n<section id=\"hints\">\n<span id=\"topics-db-multi-db-hints\"></span><h4>힌트<a class=\"heading-anchor\" href=\"#hints\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>The hints received by the database router can be used to decide which\ndatabase should receive a given request.</p>\n<p>At present, the only hint that will be provided is <code class=\"docutils literal notranslate\"><span class=\"pre\">instance</span></code>, an\nobject instance that is related to the read or write operation that is\nunderway. This might be the instance that is being saved, or it might\nbe an instance that is being added in a many-to-many relation. In some\ncases, no instance hint will be provided at all. The router checks for\nthe existence of an instance hint, and determine if that hint should be\nused to alter routing behavior.</p>\n</section>\n</section>\n<section id=\"using-routers\">\n<h3>라우터 사용하기<a class=\"heading-anchor\" href=\"#using-routers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Database routers are installed using the <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASE_ROUTERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE_ROUTERS</span></code></a>\nsetting. This setting defines a list of class names, each specifying a\nrouter that should be used by the master router\n(<code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.router</span></code>).</p>\n<p>The master router is used by Django’s database operations to allocate\ndatabase usage. Whenever a query needs to know which database to use,\nit calls the master router, providing a model and a hint (if\navailable). Django then tries each router in turn until a database\nsuggestion can be found. If no suggestion can be found, it tries the\ncurrent <a class=\"reference internal\" href=\"/ko/3.2/ref/models/instances/#django.db.models.Model._state\" title=\"django.db.models.Model._state\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">instance._state.db</span></code></a> of the hint\ninstance. If a hint instance wasn’t provided, or <a class=\"reference internal\" href=\"/ko/3.2/ref/models/instances/#django.db.models.Model._state\" title=\"django.db.models.Model._state\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">instance._state.db</span></code></a> is <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>, the master router will allocate\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database.</p>\n</section>\n<section id=\"an-example\">\n<h3>예제:<a class=\"heading-anchor\" href=\"#an-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"admonition-example-purposes-only admonition\">\n<p class=\"admonition-title\">Example purposes only!</p>\n<p>This example is intended as a demonstration of how the router\ninfrastructure can be used to alter database usage. It\nintentionally ignores some complex issues in order to\ndemonstrate how routers are used.</p>\n<p>This example won’t work if any of the models in <code class=\"docutils literal notranslate\"><span class=\"pre\">myapp</span></code> contain\nrelationships to models outside of the <code class=\"docutils literal notranslate\"><span class=\"pre\">other</span></code> database.\n<a class=\"reference internal\" href=\"#no-cross-database-relations\"><span class=\"std std-ref\">Cross-database relationships</span></a>\nintroduce referential integrity problems that Django can’t\ncurrently handle.</p>\n<p>The primary/replica (referred to as master/slave by some databases)\nconfiguration described is also flawed – it\ndoesn’t provide any solution for handling replication lag (i.e.,\nquery inconsistencies introduced because of the time taken for a\nwrite to propagate to the replicas). It also doesn’t consider the\ninteraction of transactions with the database utilization strategy.</p>\n</aside>\n<p>So - what does this mean in practice? Let’s consider another sample\nconfiguration. This one will have several databases: one for the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> application, and all other apps using a primary/replica setup\nwith two read replicas. Here are the settings specifying these\ndatabases:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASES</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;default&#39;</span><span class=\"p\">:</span> <span class=\"p\">{},</span>\n    <span class=\"s1\">&#39;auth_db&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;auth_db_name&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;swordfish&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;primary&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;primary_name&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;spam&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;replica1&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;replica1_name&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;eggs&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;replica2&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;replica2_name&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;ENGINE&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.db.backends.mysql&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;USER&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;mysql_user&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;PASSWORD&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;bacon&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n<p>Now we’ll need to handle routing. First we want a router that knows to\nsend queries for the <code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">contenttypes</span></code> apps to <code class=\"docutils literal notranslate\"><span class=\"pre\">auth_db</span></code>\n(<code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> models are linked to <code class=\"docutils literal notranslate\"><span class=\"pre\">ContentType</span></code>, so they must be stored in the\nsame database):</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthRouter</span><span class=\"p\">:</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    A router to control all database operations on models in the</span>\n<span class=\"sd\">    auth and contenttypes applications.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">route_app_labels</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;auth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;contenttypes&#39;</span><span class=\"p\">}</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_for_read</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Attempts to read auth and contenttypes models go to auth_db.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">if</span> <span class=\"n\">model</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">app_label</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">route_app_labels</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;auth_db&#39;</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_for_write</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Attempts to write auth and contenttypes models go to auth_db.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">if</span> <span class=\"n\">model</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">app_label</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">route_app_labels</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"s1\">&#39;auth_db&#39;</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allow_relation</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">obj1</span><span class=\"p\">,</span> <span class=\"n\">obj2</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Allow relations if a model in the auth or contenttypes apps is</span>\n<span class=\"sd\">        involved.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">if</span> <span class=\"p\">(</span>\n            <span class=\"n\">obj1</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">app_label</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">route_app_labels</span> <span class=\"ow\">or</span>\n            <span class=\"n\">obj2</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">app_label</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">route_app_labels</span>\n        <span class=\"p\">):</span>\n           <span class=\"k\">return</span> <span class=\"kc\">True</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allow_migrate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db</span><span class=\"p\">,</span> <span class=\"n\">app_label</span><span class=\"p\">,</span> <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Make sure the auth and contenttypes apps only appear in the</span>\n<span class=\"sd\">        &#39;auth_db&#39; database.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">if</span> <span class=\"n\">app_label</span> <span class=\"ow\">in</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">route_app_labels</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">db</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;auth_db&#39;</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n</code></pre></div>\n<p>And we also want a router that sends all other apps to the\nprimary/replica configuration, and randomly chooses a replica to read\nfrom:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">random</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PrimaryReplicaRouter</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_for_read</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Reads go to a randomly-chosen replica.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">random</span><span class=\"o\">.</span><span class=\"n\">choice</span><span class=\"p\">([</span><span class=\"s1\">&#39;replica1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;replica2&#39;</span><span class=\"p\">])</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">db_for_write</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">model</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Writes always go to primary.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"s1\">&#39;primary&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allow_relation</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">obj1</span><span class=\"p\">,</span> <span class=\"n\">obj2</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Relations between objects are allowed if both objects are</span>\n<span class=\"sd\">        in the primary/replica pool.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">db_set</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">&#39;primary&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;replica1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;replica2&#39;</span><span class=\"p\">}</span>\n        <span class=\"k\">if</span> <span class=\"n\">obj1</span><span class=\"o\">.</span><span class=\"n\">_state</span><span class=\"o\">.</span><span class=\"n\">db</span> <span class=\"ow\">in</span> <span class=\"n\">db_set</span> <span class=\"ow\">and</span> <span class=\"n\">obj2</span><span class=\"o\">.</span><span class=\"n\">_state</span><span class=\"o\">.</span><span class=\"n\">db</span> <span class=\"ow\">in</span> <span class=\"n\">db_set</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"kc\">True</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">allow_migrate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db</span><span class=\"p\">,</span> <span class=\"n\">app_label</span><span class=\"p\">,</span> <span class=\"n\">model_name</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">hints</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        All non-auth models end up in this pool.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n</code></pre></div>\n<p>Finally, in the settings file, we add the following (substituting\n<code class=\"docutils literal notranslate\"><span class=\"pre\">path.to.</span></code> with the actual Python path to the module(s) where the\nrouters are defined):</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">DATABASE_ROUTERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;path.to.AuthRouter&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;path.to.PrimaryReplicaRouter&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>The order in which routers are processed is significant. Routers will\nbe queried in the order they are listed in the\n<a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASE_ROUTERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE_ROUTERS</span></code></a> setting. In this example, the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">AuthRouter</span></code> is processed before the <code class=\"docutils literal notranslate\"><span class=\"pre\">PrimaryReplicaRouter</span></code>, and as a\nresult, decisions concerning the models in <code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> are processed\nbefore any other decision is made. If the <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-DATABASE_ROUTERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASE_ROUTERS</span></code></a>\nsetting listed the two routers in the other order,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">PrimaryReplicaRouter.allow_migrate()</span></code> would be processed first. The\ncatch-all nature of the PrimaryReplicaRouter implementation would mean\nthat all models would be available on all databases.</p>\n<p>With this setup installed, and all databases migrated as per\n<a class=\"reference internal\" href=\"#synchronizing-multiple-databases\"><span class=\"std std-ref\">데이터베이스 연동</span></a>, lets run some Django code:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This retrieval will be performed on the &#39;auth_db&#39; database</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">fred</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;fred&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">fred</span><span class=\"o\">.</span><span class=\"n\">first_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;Frederick&#39;</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This save will also be directed to &#39;auth_db&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">fred</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># These retrieval will be randomly allocated to a replica database</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">dna</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;Douglas Adams&#39;</span><span class=\"p\">)</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># A new object has no database allocation when created</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">mh</span> <span class=\"o\">=</span> <span class=\"n\">Book</span><span class=\"p\">(</span><span class=\"n\">title</span><span class=\"o\">=</span><span class=\"s1\">&#39;Mostly Harmless&#39;</span><span class=\"p\">)</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This assignment will consult the router, and set mh onto</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># the same database as the author object</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">mh</span><span class=\"o\">.</span><span class=\"n\">author</span> <span class=\"o\">=</span> <span class=\"n\">dna</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This save will force the &#39;mh&#39; instance onto the primary database...</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">mh</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># ... but if we re-retrieve the object, it will come back on a replica</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">mh</span> <span class=\"o\">=</span> <span class=\"n\">Book</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">title</span><span class=\"o\">=</span><span class=\"s1\">&#39;Mostly Harmless&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>This example defined a router to handle interaction with models from the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> app, and other routers to handle interaction with all other apps. If\nyou left your <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database empty and don’t want to define a catch-all\ndatabase router to handle all apps not otherwise specified, your routers must\nhandle the names of all apps in <a class=\"reference internal\" href=\"/ko/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> before you migrate.\nSee <a class=\"reference internal\" href=\"#contrib-app-multiple-databases\"><span class=\"std std-ref\">Behavior of contrib apps</span></a> for information about contrib apps\nthat must be together in one database.</p>\n</section>\n</section>\n<section id=\"manually-selecting-a-database\">\n<h2>수동으로 데이터베이스 선택하기<a class=\"heading-anchor\" href=\"#manually-selecting-a-database\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django also provides an API that allows you to maintain complete control\nover database usage in your code. A manually specified database allocation\nwill take priority over a database allocated by a router.</p>\n<section id=\"manually-selecting-a-database-for-a-queryset\">\n<h3>“QuerySet”을 위해 수동으로 데이티베이스 선택하기<a class=\"heading-anchor\" href=\"#manually-selecting-a-database-for-a-queryset\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>You can select the database for a <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> at any point in the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> “chain.” Call <code class=\"docutils literal notranslate\"><span class=\"pre\">using()</span></code> on the <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> to get another\n<code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> that uses the specified database.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">using()</span></code> takes a single argument: the alias of the database on\nwhich you want to run the query. For example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This will run on the &#39;default&#39; database.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Author</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># So will this.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Author</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"s1\">&#39;default&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># This will run on the &#39;other&#39; database.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Author</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"s1\">&#39;other&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n</code></pre></div>\n</section>\n<section id=\"selecting-a-database-for-save\">\n<h3>Selecting a database for <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code><a class=\"heading-anchor\" href=\"#selecting-a-database-for-save\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Use the <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> keyword to <code class=\"docutils literal notranslate\"><span class=\"pre\">Model.save()</span></code> to specify to which\ndatabase the data should be saved.</p>\n<p>For example, to save an object to the <code class=\"docutils literal notranslate\"><span class=\"pre\">legacy_users</span></code> database, you’d\nuse this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">my_object</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;legacy_users&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>If you don’t specify <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code>, the <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> method will save into\nthe default database allocated by the routers.</p>\n<section id=\"moving-an-object-from-one-database-to-another\">\n<h4>Moving an object from one database to another<a class=\"heading-anchor\" href=\"#moving-an-object-from-one-database-to-another\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>If you’ve saved an instance to one database, it might be tempting to\nuse <code class=\"docutils literal notranslate\"><span class=\"pre\">save(using=...)</span></code> as a way to migrate the instance to a new\ndatabase. However, if you don’t take appropriate steps, this could\nhave some unexpected consequences.</p>\n<p>다음 예제를 참고하세요:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;Fred&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;first&#39;</span><span class=\"p\">)</span>  <span class=\"c1\"># (statement 1)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;second&#39;</span><span class=\"p\">)</span> <span class=\"c1\"># (statement 2)</span>\n</code></pre></div>\n<p>In statement 1, a new <code class=\"docutils literal notranslate\"><span class=\"pre\">Person</span></code> object is saved to the <code class=\"docutils literal notranslate\"><span class=\"pre\">first</span></code>\ndatabase. At this time, <code class=\"docutils literal notranslate\"><span class=\"pre\">p</span></code> doesn’t have a primary key, so Django\nissues an SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">INSERT</span></code> statement. This creates a primary key, and\nDjango assigns that primary key to <code class=\"docutils literal notranslate\"><span class=\"pre\">p</span></code>.</p>\n<p>When the save occurs in statement 2, <code class=\"docutils literal notranslate\"><span class=\"pre\">p</span></code> already has a primary key\nvalue, and Django will attempt to use that primary key on the new\ndatabase. If the primary key value isn’t in use in the <code class=\"docutils literal notranslate\"><span class=\"pre\">second</span></code>\ndatabase, then you won’t have any problems – the object will be\ncopied to the new database.</p>\n<p>However, if the primary key of <code class=\"docutils literal notranslate\"><span class=\"pre\">p</span></code> is already in use on the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">second</span></code> database, the existing object in the <code class=\"docutils literal notranslate\"><span class=\"pre\">second</span></code> database\nwill be overridden when <code class=\"docutils literal notranslate\"><span class=\"pre\">p</span></code> is saved.</p>\n<p>You can avoid this in two ways. First, you can clear the primary key\nof the instance. If an object has no primary key, Django will treat it\nas a new object, avoiding any loss of data on the <code class=\"docutils literal notranslate\"><span class=\"pre\">second</span></code>\ndatabase:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;Fred&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;first&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">pk</span> <span class=\"o\">=</span> <span class=\"kc\">None</span> <span class=\"c1\"># Clear the primary key.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;second&#39;</span><span class=\"p\">)</span> <span class=\"c1\"># Write a completely new object.</span>\n</code></pre></div>\n<p>The second option is to use the <code class=\"docutils literal notranslate\"><span class=\"pre\">force_insert</span></code> option to <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code>\nto ensure that Django does an SQL <code class=\"docutils literal notranslate\"><span class=\"pre\">INSERT</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span> <span class=\"o\">=</span> <span class=\"n\">Person</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;Fred&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;first&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;second&#39;</span><span class=\"p\">,</span> <span class=\"n\">force_insert</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>This will ensure that the person named <code class=\"docutils literal notranslate\"><span class=\"pre\">Fred</span></code> will have the same\nprimary key on both databases. If that primary key is already in use\nwhen you try to save onto the <code class=\"docutils literal notranslate\"><span class=\"pre\">second</span></code> database, an error will be\nraised.</p>\n</section>\n</section>\n<section id=\"selecting-a-database-to-delete-from\">\n<h3>Selecting a database to delete from<a class=\"heading-anchor\" href=\"#selecting-a-database-to-delete-from\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>By default, a call to delete an existing object will be executed on\nthe same database that was used to retrieve the object in the first\nplace:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">u</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"s1\">&#39;legacy_users&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;fred&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">u</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">()</span> <span class=\"c1\"># will delete from the `legacy_users` database</span>\n</code></pre></div>\n<p>To specify the database from which a model will be deleted, pass a\n<code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> keyword argument to the <code class=\"docutils literal notranslate\"><span class=\"pre\">Model.delete()</span></code> method. This\nargument works just like the <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> keyword argument to <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code>.</p>\n<p>For example, if you’re migrating a user from the <code class=\"docutils literal notranslate\"><span class=\"pre\">legacy_users</span></code>\ndatabase to the <code class=\"docutils literal notranslate\"><span class=\"pre\">new_users</span></code> database, you might use these commands:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">user_obj</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;new_users&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">user_obj</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s1\">&#39;legacy_users&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"using-managers-with-multiple-databases\">\n<h3>Using managers with multiple databases<a class=\"heading-anchor\" href=\"#using-managers-with-multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Use the <code class=\"docutils literal notranslate\"><span class=\"pre\">db_manager()</span></code> method on managers to give managers access to\na non-default database.</p>\n<p>For example, say you have a custom manager method that touches the\ndatabase – <code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects.create_user()</span></code>. Because <code class=\"docutils literal notranslate\"><span class=\"pre\">create_user()</span></code>\nis a manager method, not a <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> method, you can’t do\n<code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects.using('new_users').create_user()</span></code>. (The\n<code class=\"docutils literal notranslate\"><span class=\"pre\">create_user()</span></code> method is only available on <code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects</span></code>, the\nmanager, not on <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> objects derived from the manager.) The\nsolution is to use <code class=\"docutils literal notranslate\"><span class=\"pre\">db_manager()</span></code>, like this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">db_manager</span><span class=\"p\">(</span><span class=\"s1\">&#39;new_users&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">create_user</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">db_manager()</span></code> returns a copy of the manager bound to the database you specify.</p>\n<section id=\"using-get-queryset-with-multiple-databases\">\n<h4>Using <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> with multiple databases<a class=\"heading-anchor\" href=\"#using-get-queryset-with-multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>If you’re overriding <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> on your manager, be sure to\neither call the method on the parent (using <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code>) or do the\nappropriate handling of the <code class=\"docutils literal notranslate\"><span class=\"pre\">_db</span></code> attribute on the manager (a string\ncontaining the name of the database to use).</p>\n<p>For example, if you want to return a custom <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> class from\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset</span></code> method, you could do this:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyManager</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Manager</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">qs</span> <span class=\"o\">=</span> <span class=\"n\">CustomQuerySet</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">model</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">_db</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n            <span class=\"n\">qs</span> <span class=\"o\">=</span> <span class=\"n\">qs</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">_db</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">qs</span>\n</code></pre></div>\n</section>\n</section>\n</section>\n<section id=\"exposing-multiple-databases-in-django-s-admin-interface\">\n<h2>Exposing multiple databases in Django’s admin interface<a class=\"heading-anchor\" href=\"#exposing-multiple-databases-in-django-s-admin-interface\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django’s admin doesn’t have any explicit support for multiple\ndatabases. If you want to provide an admin interface for a model on a\ndatabase other than that specified by your router chain, you’ll\nneed to write custom <a class=\"reference internal\" href=\"/ko/3.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin\" title=\"django.contrib.admin.ModelAdmin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelAdmin</span></code></a> classes\nthat will direct the admin to use a specific database for content.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">ModelAdmin</span></code> objects have five methods that require customization for\nmultiple-database support:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MultiDBModelAdmin</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">ModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"c1\"># A handy constant for the name of the alternate database.</span>\n    <span class=\"n\">using</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;other&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">save_model</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">obj</span><span class=\"p\">,</span> <span class=\"n\">form</span><span class=\"p\">,</span> <span class=\"n\">change</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to save objects to the &#39;other&#39; database.</span>\n        <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">delete_model</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">obj</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to delete objects from the &#39;other&#39; database</span>\n        <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to look for objects on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_queryset</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">formfield_for_foreignkey</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to populate ForeignKey widgets using a query</span>\n        <span class=\"c1\"># on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">formfield_for_foreignkey</span><span class=\"p\">(</span><span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">formfield_for_manytomany</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to populate ManyToMany widgets using a query</span>\n        <span class=\"c1\"># on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">formfield_for_manytomany</span><span class=\"p\">(</span><span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>The implementation provided here implements a multi-database strategy\nwhere all objects of a given type are stored on a specific database\n(e.g., all <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> objects are in the <code class=\"docutils literal notranslate\"><span class=\"pre\">other</span></code> database). If your\nusage of multiple databases is more complex, your <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelAdmin</span></code> will\nneed to reflect that strategy.</p>\n<p><a class=\"reference internal\" href=\"/ko/3.2/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin\" title=\"django.contrib.admin.InlineModelAdmin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">InlineModelAdmin</span></code></a> objects can be handled in a\nsimilar fashion. They require three customized methods:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MultiDBTabularInline</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">TabularInline</span><span class=\"p\">):</span>\n    <span class=\"n\">using</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;other&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to look for inline objects on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_queryset</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">formfield_for_foreignkey</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to populate ForeignKey widgets using a query</span>\n        <span class=\"c1\"># on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">formfield_for_foreignkey</span><span class=\"p\">(</span><span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">formfield_for_manytomany</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Tell Django to populate ManyToMany widgets using a query</span>\n        <span class=\"c1\"># on the &#39;other&#39; database.</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">formfield_for_manytomany</span><span class=\"p\">(</span><span class=\"n\">db_field</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">using</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Once you’ve written your model admin definitions, they can be\nregistered with any <code class=\"docutils literal notranslate\"><span class=\"pre\">Admin</span></code> instance:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"c1\"># Specialize the multi-db admin objects for use with specific models.</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">BookInline</span><span class=\"p\">(</span><span class=\"n\">MultiDBTabularInline</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Book</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PublisherAdmin</span><span class=\"p\">(</span><span class=\"n\">MultiDBModelAdmin</span><span class=\"p\">):</span>\n    <span class=\"n\">inlines</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"n\">BookInline</span><span class=\"p\">]</span>\n\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Author</span><span class=\"p\">,</span> <span class=\"n\">MultiDBModelAdmin</span><span class=\"p\">)</span>\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Publisher</span><span class=\"p\">,</span> <span class=\"n\">PublisherAdmin</span><span class=\"p\">)</span>\n\n<span class=\"n\">othersite</span> <span class=\"o\">=</span> <span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">AdminSite</span><span class=\"p\">(</span><span class=\"s1\">&#39;othersite&#39;</span><span class=\"p\">)</span>\n<span class=\"n\">othersite</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Publisher</span><span class=\"p\">,</span> <span class=\"n\">MultiDBModelAdmin</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>This example sets up two admin sites. On the first site, the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> objects are exposed; <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code>\nobjects have a tabular inline showing books published by that\npublisher. The second site exposes just publishers, without the\ninlines.</p>\n</section>\n<section id=\"using-raw-cursors-with-multiple-databases\">\n<h2>Using raw cursors with multiple databases<a class=\"heading-anchor\" href=\"#using-raw-cursors-with-multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>If you are using more than one database you can use\n<code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connections</span></code> to obtain the connection (and cursor) for a\nspecific database. <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connections</span></code> is a dictionary-like\nobject that allows you to retrieve a specific connection using its\nalias:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">connections</span>\n<span class=\"k\">with</span> <span class=\"n\">connections</span><span class=\"p\">[</span><span class=\"s1\">&#39;my_db_alias&#39;</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">cursor</span><span class=\"p\">()</span> <span class=\"k\">as</span> <span class=\"n\">cursor</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"limitations-of-multiple-databases\">\n<h2>다중 데이터베이스의 제한<a class=\"heading-anchor\" href=\"#limitations-of-multiple-databases\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"cross-database-relations\">\n<span id=\"no-cross-database-relations\"></span><h3>크로스-데이터베이스 관계<a class=\"heading-anchor\" href=\"#cross-database-relations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django doesn’t currently provide any support for foreign key or\nmany-to-many relationships spanning multiple databases. If you\nhave used a router to partition models to different databases,\nany foreign key and many-to-many relationships defined by those\nmodels must be internal to a single database.</p>\n<p>This is because of referential integrity. In order to maintain a\nrelationship between two objects, Django needs to know that the\nprimary key of the related object is valid. If the primary key is\nstored on a separate database, it’s not possible to easily evaluate\nthe validity of a primary key.</p>\n<p>If you’re using Postgres, Oracle, or MySQL with InnoDB, this is\nenforced at the database integrity level – database level key\nconstraints prevent the creation of relations that can’t be validated.</p>\n<p>However, if you’re using SQLite or MySQL with MyISAM tables, there is\nno enforced referential integrity; as a result, you may be able to\n‘fake’ cross database foreign keys. However, this configuration is not\nofficially supported by Django.</p>\n</section>\n<section id=\"behavior-of-contrib-apps\">\n<span id=\"contrib-app-multiple-databases\"></span><h3>Behavior of contrib apps<a class=\"heading-anchor\" href=\"#behavior-of-contrib-apps\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Several contrib apps include models, and some apps depend on others. Since\ncross-database relationships are impossible, this creates some restrictions on\nhow you can split these models across databases:</p>\n<ul class=\"simple\">\n<li><p>each one of <code class=\"docutils literal notranslate\"><span class=\"pre\">contenttypes.ContentType</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">sessions.Session</span></code> and\n<code class=\"docutils literal notranslate\"><span class=\"pre\">sites.Site</span></code> can be stored in any database, given a suitable router.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code> models — <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">Group</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">Permission</span></code> — are linked\ntogether and linked to <code class=\"docutils literal notranslate\"><span class=\"pre\">ContentType</span></code>, so they must be stored in the same\ndatabase as <code class=\"docutils literal notranslate\"><span class=\"pre\">ContentType</span></code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">admin</span></code> depends on <code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code>, so its models must be in the same database\nas <code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code>.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">flatpages</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">redirects</span></code> depend on <code class=\"docutils literal notranslate\"><span class=\"pre\">sites</span></code>, so their models must be\nin the same database as <code class=\"docutils literal notranslate\"><span class=\"pre\">sites</span></code>.</p></li>\n</ul>\n<p>In addition, some objects are automatically created just after\n<a class=\"reference internal\" href=\"/ko/3.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> creates a table to hold them in a database:</p>\n<ul class=\"simple\">\n<li><p>a default <code class=\"docutils literal notranslate\"><span class=\"pre\">Site</span></code>,</p></li>\n<li><p>a <code class=\"docutils literal notranslate\"><span class=\"pre\">ContentType</span></code> for each model (including those not stored in that\ndatabase),</p></li>\n<li><p>the <code class=\"docutils literal notranslate\"><span class=\"pre\">Permission</span></code>s for each model (including those not stored in that\ndatabase).</p></li>\n</ul>\n<p>For common setups with multiple databases, it isn’t useful to have these\nobjects in more than one database. Common setups include primary/replica and\nconnecting to external databases. Therefore, it’s recommended to write a\n<a class=\"reference internal\" href=\"#topics-db-multi-db-routing\"><span class=\"std std-ref\">database router</span></a> that allows synchronizing\nthese three models to only one database. Use the same approach for contrib\nand third-party apps that don’t need their tables in multiple databases.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">경고</p>\n<p>If you’re synchronizing content types to more than one database, be aware\nthat their primary keys may not match across databases. This may result in\ndata corruption or data loss.</p>\n</aside>\n</section>\n</section>","rootId":"multiple-databases","toc":[{"title":"데이터베이스 정의","anchor":"defining-your-databases","children":[]},{"title":"데이터베이스 연동","anchor":"synchronizing-your-databases","children":[{"title":"다른 관리 명령어 사용하기","anchor":"using-other-management-commands","children":[]}]},{"title":"Automatic database routing","anchor":"automatic-database-routing","children":[{"title":"데이터베이스 라우터","anchor":"database-routers","children":[{"title":"힌트","anchor":"hints","children":[]}]},{"title":"라우터 사용하기","anchor":"using-routers","children":[]},{"title":"예제:","anchor":"an-example","children":[]}]},{"title":"수동으로 데이터베이스 선택하기","anchor":"manually-selecting-a-database","children":[{"title":"“QuerySet”을 위해 수동으로 데이티베이스 선택하기","anchor":"manually-selecting-a-database-for-a-queryset","children":[]},{"title":"Selecting a database for save()","anchor":"selecting-a-database-for-save","children":[{"title":"Moving an object from one database to another","anchor":"moving-an-object-from-one-database-to-another","children":[]}]},{"title":"Selecting a database to delete from","anchor":"selecting-a-database-to-delete-from","children":[]},{"title":"Using managers with multiple databases","anchor":"using-managers-with-multiple-databases","children":[{"title":"Using get_queryset() with multiple databases","anchor":"using-get-queryset-with-multiple-databases","children":[]}]}]},{"title":"Exposing multiple databases in Django’s admin interface","anchor":"exposing-multiple-databases-in-django-s-admin-interface","children":[]},{"title":"Using raw cursors with multiple databases","anchor":"using-raw-cursors-with-multiple-databases","children":[]},{"title":"다중 데이터베이스의 제한","anchor":"limitations-of-multiple-databases","children":[{"title":"크로스-데이터베이스 관계","anchor":"cross-database-relations","children":[]},{"title":"Behavior of contrib apps","anchor":"behavior-of-contrib-apps","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django 사용하기","url":"/ko/3.2/topics/"},{"docname":"topics/db/index","title":"모델과 데이터베이스","url":"/ko/3.2/topics/db/"}],"prev":{"docname":"topics/db/transactions","title":"데이터베이스 트랜잭션","url":"/ko/3.2/topics/db/transactions/"},"next":{"docname":"topics/db/tablespaces","title":"테이블스페이스","url":"/ko/3.2/topics/db/tablespaces/"},"formats":{"html":"/ko/3.2/topics/db/multi-db/","markdown":"/ko/3.2/topics/db/multi-db.md","json":"/ko/3.2/topics/db/multi-db.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/topics/db/multi-db.txt","official":"https://docs.djangoproject.com/ko/3.2/topics/db/multi-db/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}