---
title: "Basisdata banyak"
version: 1.10
locale: id
source: https://docs.djangoproject.com/id/1.10/topics/db/multi-db/
canonical: https://djangodocs.dev/id/1.10/topics/db/multi-db/
---
# Basisdata banyak

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 single database. If you want to interact
with multiple databases, you'll need to take some additional steps.

## Menentukan basisdata anda

Langkah pertama untuk menggunakan lebih dari satu basisdata dengan Django adalah memberitahu Django tentang peladen basisdata anda akan gunakan. Ini dilakukan menggunakan pengaturan [`DATABASES`](/id/1.10/ref/settings/#std-setting-DATABASES). Pengaturan ini memetakan nama lain basisdata, yang adalah cara mengacu ke basisdata tertentu sepanjang Django, ke sebuah kamus dari pengaturan untuk hubungan tertentu itu. Pengaturan di sebelah dalam kamus digambarkan sepenuhnya dalam dokumentasi [`DATABASES`](/id/1.10/ref/settings/#std-setting-DATABASES).

Databases can have any alias you choose. However, the alias
`default` has special significance. Django uses the database with
the alias of `default` when no other database has been selected.

The following is an example `settings.py` snippet defining two
databases -- a default PostgreSQL database and a MySQL database called
`users`:

```
DATABASES = {
    'default': {
        'NAME': 'app_data',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 's3krit'
    },
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'priv4te'
    }
}
```

If the concept of a `default` database doesn't make sense in the context
of your project, you need to be careful to always specify the database
that you want to use. Django requires that a `default` database entry
be defined, but the parameters dictionary can be left blank if it will not be
used. To do this, you must set up [`DATABASE_ROUTERS`](/id/1.10/ref/settings/#std-setting-DATABASE_ROUTERS) for all of your
apps' models, including those in any contrib and third-party apps you're using,
so that no queries are routed to the default database. The following is an
example `settings.py` snippet defining two non-default databases, with the
`default` entry intentionally left empty:

```
DATABASES = {
    'default': {},
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'superS3cret'
    },
    'customers': {
        'NAME': 'customer_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_cust',
        'PASSWORD': 'veryPriv@ate'
    }
}
```

If you attempt to access a database that you haven't defined in your
[`DATABASES`](/id/1.10/ref/settings/#std-setting-DATABASES) setting, Django will raise a
`django.db.utils.ConnectionDoesNotExist` exception.

## Sinkronisasi basisdata anda

The [`migrate`](/id/1.10/ref/django-admin/#django-admin-migrate) management command operates on one database at a
time. By default, it operates on the `default` database, but by
providing the [`--database`](/id/1.10/ref/django-admin/#cmdoption-migrate-database) option, you can tell it
to synchronize a different database. So, to synchronize all models onto
all databases in the first example above, you would need to call:

```
$ ./manage.py migrate
$ ./manage.py migrate --database=users
```

If you don't want every application to be synchronized onto a
particular database, you can define a [database
router](#topics-db-multi-db-routing) that implements a policy
constraining the availability of particular models.

If, as in the second example above, you've left the `default` database empty,
you must provide a database name each time you run [`migrate`](/id/1.10/ref/django-admin/#django-admin-migrate). Omitting
the database name would raise an error. For the second example:

```
$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers
```

### Using other management commands

Most other `django-admin` commands that interact with the database operate in
the same way as [`migrate`](/id/1.10/ref/django-admin/#django-admin-migrate) -- they only ever operate on one database at
a time, using `--database` to control the database used.

Sebuah pengecualian pada aturan ini adalah perintah [`makemigrations`](/id/1.10/ref/django-admin/#django-admin-makemigrations). Itu mengecek riwayat perpindahan di basisdata untuk menangkap masalah dengan berkas perpindahan yang ada (yang dapat disebabkan dengan menyunting mereka) sebelum membuat perpindahan baru. Secara awalan, itu memeriksa hanya basisdata `default`, tetapi itu merundingkan metode [`allow_migrate()`](#allow_migrate) dari [routers](#topics-db-multi-db-routing) jika apapun terpasang.

> **Changed in Django 1.10**
>
> Migration consistency checks were added. Checks based on database routers
> were added in 1.10.1.

## Automatic database routing

The easiest way to use multiple databases is to set up a database
routing scheme. The default routing scheme ensures that objects remain
'sticky' to their original database (i.e., an object retrieved from
the `foo` database will be saved on the same database). The default
routing scheme ensures that if a database isn't specified, all queries
fall back to the `default` database.

You don't have to do anything to activate the default routing scheme
-- it is provided 'out of the box' on every Django project. However,
if you want to implement more interesting database allocation
behaviors, you can define and install your own database routers.

### Router basisdata

Perute basisdata adalah kelas yang menyediakan sampai empat metode:

#### `db_for_read(model, **hints)`

Suggest the database that should be used for read operations for
objects of type `model`.

If a database operation is able to provide any additional
information that might assist in selecting a database, it will be
provided in the `hints` dictionary. Details on valid hints are
provided [below](#topics-db-multi-db-hints).

Mengembalikan `None` jika tidak ada saran.

#### `db_for_write(model, **hints)`

Suggest the database that should be used for writes of objects of
type Model.

If a database operation is able to provide any additional
information that might assist in selecting a database, it will be
provided in the `hints` dictionary. Details on valid hints are
provided [below](#topics-db-multi-db-hints).

Mengembalikan `None` jika tidak ada saran.

#### `allow_relation(obj1, obj2, **hints)`

Mengembalikan `True` jika sebuah hubungan diantara `obj1` dan `obj2` harus diizinkan, `False` jika hubungan harus dicegah, atau `None` jika perute tidak memiliki pendapat. Ini adalah murni tindakan pengesahan, digunakan oleh foreign key dan tindakan many to many untuk menentukan jika hubungan harus diizinkan diantara dua obyek.

#### `allow_migrate(db, app_label, model_name=None, **hints)`

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

The `app_label` positional argument is the label of the application
being migrated.

`model_name` is set by most migration operations to the value of
`model._meta.model_name` (the lowercased version of the model
`__name__`) of the model being migrated. Its value is `None` for the
[`RunPython`](/id/1.10/ref/migration-operations/#django.db.migrations.operations.RunPython) and
[`RunSQL`](/id/1.10/ref/migration-operations/#django.db.migrations.operations.RunSQL) operations unless they
provide it using hints.

`hints` are used by certain operations to communicate additional
information to the router.

When `model_name` is set, `hints` normally contains the model class
under the key `'model'`. Note that it may be a [historical model](/id/1.10/topics/migrations/#historical-models), and thus not have any custom attributes, methods, or
managers. You should only rely on `_meta`.

This method can also be used to determine the availability of a model on a
given database.

[`makemigrations`](/id/1.10/ref/django-admin/#django-admin-makemigrations) always creates migrations for model changes, but
if `allow_migrate()` returns `False`, any migration operations for the
`model_name` will be silently skipped when running [`migrate`](/id/1.10/ref/django-admin/#django-admin-migrate) on
the `db`. Changing the behavior of `allow_migrate()` for models that
already have migrations may result in broken foreign keys, extra tables,
or missing tables. When [`makemigrations`](/id/1.10/ref/django-admin/#django-admin-makemigrations) verifies the migration
history, it skips databases where no app is allowed to migrate.

A router doesn't have to provide *all* these methods -- it may omit one
or more of them. If one of the methods is omitted, Django will skip
that router when performing the relevant check.

#### Petunjuk

The hints received by the database router can be used to decide which
database should receive a given request.

At present, the only hint that will be provided is `instance`, an
object instance that is related to the read or write operation that is
underway. This might be the instance that is being saved, or it might
be an instance that is being added in a many-to-many relation. In some
cases, no instance hint will be provided at all. The router checks for
the existence of an instance hint, and determine if that hint should be
used to alter routing behavior.

### Menggunakan router

Database routers are installed using the [`DATABASE_ROUTERS`](/id/1.10/ref/settings/#std-setting-DATABASE_ROUTERS)
setting. This setting defines a list of class names, each specifying a
router that should be used by the master router
(`django.db.router`).

The master router is used by Django's database operations to allocate
database usage. Whenever a query needs to know which database to use,
it calls the master router, providing a model and a hint (if
available). Django then tries each router in turn until a database
suggestion can be found. If no suggestion can be found, it tries the
current `_state.db` of the hint instance. If a hint instance wasn't
provided, or the instance doesn't currently have database state, the
master router will allocate the `default` database.

### Sebuah contoh

> **Hanya bertujuan contoh!**
>
> This example is intended as a demonstration of how the router
> infrastructure can be used to alter database usage. It
> intentionally ignores some complex issues in order to
> demonstrate how routers are used.
>
> This example won't work if any of the models in `myapp` contain
> relationships to models outside of the `other` database.
> [Cross-database relationships](#no-cross-database-relations)
> introduce referential integrity problems that Django can't
> currently handle.
>
> The primary/replica (referred to as master/slave by some databases)
> configuration described is also flawed -- it
> doesn't provide any solution for handling replication lag (i.e.,
> query inconsistencies introduced because of the time taken for a
> write to propagate to the replicas). It also doesn't consider the
> interaction of transactions with the database utilization strategy.

So - what does this mean in practice? Let's consider another sample
configuration. This one will have several databases: one for the
`auth` application, and all other apps using a primary/replica setup
with two read replicas. Here are the settings specifying these
databases:

```
DATABASES = {
    'default': {},
    'auth_db': {
        'NAME': 'auth_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'swordfish',
    },
    'primary': {
        'NAME': 'primary',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'spam',
    },
    'replica1': {
        'NAME': 'replica1',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'eggs',
    },
    'replica2': {
        'NAME': 'replica2',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'bacon',
    },
}
```

Now we'll need to handle routing. First we want a router that knows to
send queries for the `auth` app to `auth_db`:

```
class AuthRouter(object):
    """
    A router to control all database operations on models in the
    auth application.
    """
    def db_for_read(self, model, **hints):
        """
        Attempts to read auth models go to auth_db.
        """
        if model._meta.app_label == 'auth':
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth models go to auth_db.
        """
        if model._meta.app_label == 'auth':
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth app is involved.
        """
        if obj1._meta.app_label == 'auth' or \
           obj2._meta.app_label == 'auth':
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth app only appears in the 'auth_db'
        database.
        """
        if app_label == 'auth':
            return db == 'auth_db'
        return None
```

And we also want a router that sends all other apps to the
primary/replica configuration, and randomly chooses a replica to read
from:

```
import random

class PrimaryReplicaRouter(object):
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        return random.choice(['replica1', 'replica2'])

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        return 'primary'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_list = ('primary', 'replica1', 'replica2')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        return True
```

Finally, in the settings file, we add the following (substituting
`path.to.` with the actual Python path to the module(s) where the
routers are defined):

```
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']
```

The order in which routers are processed is significant. Routers will
be queried in the order they are listed in the
[`DATABASE_ROUTERS`](/id/1.10/ref/settings/#std-setting-DATABASE_ROUTERS) setting. In this example, the
`AuthRouter` is processed before the `PrimaryReplicaRouter`, and as a
result, decisions concerning the models in `auth` are processed
before any other decision is made. If the [`DATABASE_ROUTERS`](/id/1.10/ref/settings/#std-setting-DATABASE_ROUTERS)
setting listed the two routers in the other order,
`PrimaryReplicaRouter.allow_migrate()` would be processed first. The
catch-all nature of the PrimaryReplicaRouter implementation would mean
that all models would be available on all databases.

Dengan pengaturan ini dipasang, mari kita jalankan beberapa kode Django:

```
>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username='fred')
>>> fred.first_name = 'Frederick'

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

>>> # These retrieval will be randomly allocated to a replica database
>>> dna = Person.objects.get(name='Douglas Adams')

>>> # A new object has no database allocation when created
>>> mh = Book(title='Mostly Harmless')

>>> # This assignment will consult the router, and set mh onto
>>> # the same database as the author object
>>> mh.author = dna

>>> # This save will force the 'mh' instance onto the primary database...
>>> mh.save()

>>> # ... but if we re-retrieve the object, it will come back on a replica
>>> mh = Book.objects.get(title='Mostly Harmless')
```

This example defined a router to handle interaction with models from the
`auth` app, and other routers to handle interaction with all other apps. If
you left your `default` database empty and don't want to define a catch-all
database router to handle all apps not otherwise specified, your routers must
handle the names of all apps in [`INSTALLED_APPS`](/id/1.10/ref/settings/#std-setting-INSTALLED_APPS) before you migrate.
See [Perilaku dari aplikasi bantuan](#contrib-app-multiple-databases) for information about contrib apps
that must be together in one database.

## Manual memilih basisdata

Django also provides an API that allows you to maintain complete control
over database usage in your code. A manually specified database allocation
will take priority over a database allocated by a router.

### Secara manual memilih basisdata untuk `QuerySet`

You can select the database for a `QuerySet` at any point in the
`QuerySet` "chain." Just call `using()` on the `QuerySet` to get
another `QuerySet` that uses the specified database.

`using()` takes a single argument: the alias of the database on
which you want to run the query. For example:

```
>>> # This will run on the 'default' database.
>>> Author.objects.all()

>>> # So will this.
>>> Author.objects.using('default').all()

>>> # This will run on the 'other' database.
>>> Author.objects.using('other').all()
```

### Memilih basisdata untuk `save()`

Use the `using` keyword to `Model.save()` to specify to which
database the data should be saved.

For example, to save an object to the `legacy_users` database, you'd
use this:

```
>>> my_object.save(using='legacy_users')
```

If you don't specify `using`, the `save()` method will save into
the default database allocated by the routers.

#### Memindahkan sebuah obyek dari satu basisdata ke lainnya

If you've saved an instance to one database, it might be tempting to
use `save(using=...)` as a way to migrate the instance to a new
database. However, if you don't take appropriate steps, this could
have some unexpected consequences.

Pertimbangkan contoh berikut

```
>>> p = Person(name='Fred')
>>> p.save(using='first')  # (statement 1)
>>> p.save(using='second') # (statement 2)
```

In statement 1, a new `Person` object is saved to the `first`
database. At this time, `p` doesn't have a primary key, so Django
issues an SQL `INSERT` statement. This creates a primary key, and
Django assigns that primary key to `p`.

When the save occurs in statement 2, `p` already has a primary key
value, and Django will attempt to use that primary key on the new
database. If the primary key value isn't in use in the `second`
database, then you won't have any problems -- the object will be
copied to the new database.

However, if the primary key of `p` is already in use on the
`second` database, the existing object in the `second` database
will be overridden when `p` is saved.

You can avoid this in two ways. First, you can clear the primary key
of the instance. If an object has no primary key, Django will treat it
as a new object, avoiding any loss of data on the `second`
database:

```
>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.pk = None # Clear the primary key.
>>> p.save(using='second') # Write a completely new object.
```

The second option is to use the `force_insert` option to `save()`
to ensure that Django does an SQL `INSERT`:

```
>>> p = Person(name='Fred')
>>> p.save(using='first')
>>> p.save(using='second', force_insert=True)
```

This will ensure that the person named `Fred` will have the same
primary key on both databases. If that primary key is already in use
when you try to save onto the `second` database, an error will be
raised.

### Memilih basisdata untuk menghapus dari

By default, a call to delete an existing object will be executed on
the same database that was used to retrieve the object in the first
place:

```
>>> u = User.objects.using('legacy_users').get(username='fred')
>>> u.delete() # will delete from the `legacy_users` database
```

Untuk menentukan basisdata dari model mana akan dihapus, lewatkan sebuah argumen kata kunci `using` pada metode `Model.delete()`. Argumen ini bekerja seperti argumen kata kunci `using` pada `save()`.

Sebagai contoh, jika anda sedang memindahkan pengguna dari basisdata `legacy_users` ke basisdata `new_users`, anda mungkin menggunakan perintah-perintah ini:

```
>>> user_obj.save(using='new_users')
>>> user_obj.delete(using='legacy_users')
```

### Menggunakan pengelola dengan banyak basisdata

Use the `db_manager()` method on managers to give managers access to
a non-default database.

For example, say you have a custom manager method that touches the
database -- `User.objects.create_user()`. Because `create_user()`
is a manager method, not a `QuerySet` method, you can't do
`User.objects.using('new_users').create_user()`. (The
`create_user()` method is only available on `User.objects`, the
manager, not on `QuerySet` objects derived from the manager.) The
solution is to use `db_manager()`, like this:

```
User.objects.db_manager('new_users').create_user(...)
```

`db_manager()` mengembalikan sebuah salinan dari ikatan pengelola pada basisdata anda tentukan.

#### Menggunakan `get_queryset()` dengan basisdata banyak

If you're overriding `get_queryset()` on your manager, be sure to
either call the method on the parent (using `super()`) or do the
appropriate handling of the `_db` attribute on the manager (a string
containing the name of the database to use).

Sebagai contoh, jika anda ingin mengembalikan penyesuaian kelas `QuerySet` dari metode `get_queryset`, anda dapat melakukan ini:

```
class MyManager(models.Manager):
    def get_queryset(self):
        qs = CustomQuerySet(self.model)
        if self._db is not None:
            qs = qs.using(self._db)
        return qs
```

## Memamerkan basisdata banyak di antarmuka admin Django

Django's admin doesn't have any explicit support for multiple
databases. If you want to provide an admin interface for a model on a
database other than that specified by your router chain, you'll
need to write custom [`ModelAdmin`](/id/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin) classes
that will direct the admin to use a specific database for content.

Obyek `ModelAdmin` mempunyai lima metode yang membutuhkan penyesuaian untuk dukungan banyak-basisdata:

```
class MultiDBModelAdmin(admin.ModelAdmin):
    # A handy constant for the name of the alternate database.
    using = 'other'

    def save_model(self, request, obj, form, change):
        # Tell Django to save objects to the 'other' database.
        obj.save(using=self.using)

    def delete_model(self, request, obj):
        # Tell Django to delete objects from the 'other' database
        obj.delete(using=self.using)

    def get_queryset(self, request):
        # Tell Django to look for objects on the 'other' database.
        return super(MultiDBModelAdmin, self).get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
```

The implementation provided here implements a multi-database strategy
where all objects of a given type are stored on a specific database
(e.g., all `User` objects are in the `other` database). If your
usage of multiple databases is more complex, your `ModelAdmin` will
need to reflect that strategy.

Obyek [`InlineModelAdmin`](/id/1.10/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin) dapat ditangani di gaya yang mirip. Mereka membutuhkan tiga metode penyesuaian:

```
class MultiDBTabularInline(admin.TabularInline):
    using = 'other'

    def get_queryset(self, request):
        # Tell Django to look for inline objects on the 'other' database.
        return super(MultiDBTabularInline, self).get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
```

Sekali anda telah menulis pengertian admin model anda, mereka dapat didaftarkan dengan instance `Admin` apapun:

```
from django.contrib import admin

# Specialize the multi-db admin objects for use with specific models.
class BookInline(MultiDBTabularInline):
    model = Book

class PublisherAdmin(MultiDBModelAdmin):
    inlines = [BookInline]

admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)

othersite = admin.AdminSite('othersite')
othersite.register(Publisher, MultiDBModelAdmin)
```

Contoh ini menyetel dua situs admin. Pada situs pertama, obyek `Author` dan `Publisher` diperlihatkan; obyek `Publisher` mempunyai berderet datar menunjukkan buku-buku diterbitkan oleh penerbit itu. Situs kedua memperlihatkan hanya penerbit, tanpa berderet.

## Menggunakan kursor mentah dengan banyak basisdata

Jika anda menggunakan lebih dari satu basisdata anda dapat menggunakan `django.db.connections` untuk mengambil hubungan (dan kursor) untuk basisdata tertentu. `django.db.connections` adalah objek seperti-kamus yang mengizinkan anda mengambil hubungan tertentu menggunakan nama lainnya:

```
from django.db import connections
cursor = connections['my_db_alias'].cursor()
```

## Batasan dari banyak basisdata

### Hubungan lintas-basisdata

Django doesn't currently provide any support for foreign key or
many-to-many relationships spanning multiple databases. If you
have used a router to partition models to different databases,
any foreign key and many-to-many relationships defined by those
models must be internal to a single database.

This is because of referential integrity. In order to maintain a
relationship between two objects, Django needs to know that the
primary key of the related object is valid. If the primary key is
stored on a separate database, it's not possible to easily evaluate
the validity of a primary key.

Jika anda sedang menggunakan Postgres, Oracle, atau MySQL dengan InnoDB, ini dipaksa pada tingkat kesatuan basisdata -- batasan kunci tingkatan basisdata mencegah dari pembuatan dari hubungan yang tidak dapat disahkan.

However, if you're using SQLite or MySQL with MyISAM tables, there is
no enforced referential integrity; as a result, you may be able to
'fake' cross database foreign keys. However, this configuration is not
officially supported by Django.

### Perilaku dari aplikasi bantuan

Several contrib apps include models, and some apps depend on others. Since
cross-database relationships are impossible, this creates some restrictions on
how you can split these models across databases:

- each one of `contenttypes.ContentType`, `sessions.Session` and
  `sites.Site` can be stored in any database, given a suitable router.
- `auth` models — `User`, `Group` and `Permission` — are linked
  together and linked to `ContentType`, so they must be stored in the same
  database as `ContentType`.
- `admin` bergantung pada `auth`, jadi modelnya harus di basisdata sama seperti `auth`.
- `flatpages` dan `redirects` bergantung pada `sites`,jadi model-model mereka harus di basisdata yang sama seperti `sites`.

In addition, some objects are automatically created just after
[`migrate`](/id/1.10/ref/django-admin/#django-admin-migrate) creates a table to hold them in a database:

- `Site` awal,
- sebuah `ContentType` untuk setiap model (termasuk itu tidak disimpan di basisdata itu),
- tiga `Permission` untuk setiap model (termasuk itu tidak disimpan di basisdata itu),

For common setups with multiple databases, it isn't useful to have these
objects in more than one database. Common setups include primary/replica and
connecting to external databases. Therefore, it's recommended to write a
[database router](#topics-db-multi-db-routing) that allows synchronizing
these three models to only one database. Use the same approach for contrib
and third-party apps that don't need their tables in multiple databases.

> **Warning**
>
> If you're synchronizing content types to more than one database, be aware
> that their primary keys may not match across databases. This may result in
> data corruption or data loss.
