diff --git a/django_mongodb_backend/routers.py b/django_mongodb_backend/routers.py new file mode 100644 index 000000000..60e54bbd8 --- /dev/null +++ b/django_mongodb_backend/routers.py @@ -0,0 +1,18 @@ +from django.apps import apps + +from django_mongodb_backend.models import EmbeddedModel + + +class MongoRouter: + def allow_migrate(self, db, app_label, model_name=None, **hints): + """ + EmbeddedModels don't have their own collection and must be ignored by + dumpdata. + """ + if not model_name: + return None + try: + model = apps.get_model(app_label, model_name) + except LookupError: + return None + return False if issubclass(model, EmbeddedModel) else None diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 34e8f247f..1ea0c2b48 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -32,3 +32,10 @@ logging:: }, }, } + +``dumpdata`` fails with ``CommandError: Unable to serialize database`` +---------------------------------------------------------------------- + +If running ``manage.py dumpdata`` results in ``CommandError: Unable to +serialize database: 'EmbeddedModelManager' object has no attribute using'``, +see :ref:`configuring-database-routers-setting`. diff --git a/docs/source/intro/configure.rst b/docs/source/intro/configure.rst index edbfcfff3..882cce7cc 100644 --- a/docs/source/intro/configure.rst +++ b/docs/source/intro/configure.rst @@ -154,6 +154,21 @@ it into the format above, you can use This constructs a :setting:`DATABASES` setting equivalent to the first example. +.. _configuring-database-routers-setting: + +Configuring the ``DATABASE_ROUTERS`` setting +============================================ + +If you intend to use :doc:`embedded models `, you must +configure the :setting:`DATABASE_ROUTERS` setting so that a collection for +these models isn't created and so that embedded models won't be treated as +normal models by :djadmin:`dumpdata`:: + + DATABASE_ROUTERS = ["django_mongodb_backend.routers.MongoRouter"] + +(If you've used the :djadmin:`startproject` template, this line is already +present.) + Congratulations, your project is ready to go! .. seealso:: diff --git a/docs/source/releases/5.0.x.rst b/docs/source/releases/5.0.x.rst index bfaa0e632..011647e73 100644 --- a/docs/source/releases/5.0.x.rst +++ b/docs/source/releases/5.0.x.rst @@ -17,6 +17,9 @@ Django MongoDB Backend 5.0.x - Added :doc:`async ` support. - Added the ``db_name`` parameter to :func:`~django_mongodb_backend.utils.parse_uri`. +- Added ``django_mongodb_backend.routers.MongoRouter`` to allow + :djadmin:`dumpdata` to ignore embedded models. See + :ref:`configuring-database-routers-setting`. 5.0.0 beta 0 ============ diff --git a/docs/source/releases/5.1.x.rst b/docs/source/releases/5.1.x.rst index 856fb74d5..310a17ced 100644 --- a/docs/source/releases/5.1.x.rst +++ b/docs/source/releases/5.1.x.rst @@ -17,6 +17,9 @@ Django MongoDB Backend 5.1.x - Added :doc:`async ` support. - Added the ``db_name`` parameter to :func:`~django_mongodb_backend.utils.parse_uri`. +- Added ``django_mongodb_backend.routers.MongoRouter`` to allow + :djadmin:`dumpdata` to ignore embedded models. See + :ref:`configuring-database-routers-setting`. 5.1.0 beta 0 ============ diff --git a/tests/models_/models.py b/tests/models_/models.py index e02edda0a..fa4e86ec7 100644 --- a/tests/models_/models.py +++ b/tests/models_/models.py @@ -1,5 +1,11 @@ +from django.db import models + from django_mongodb_backend.models import EmbeddedModel class Embed(EmbeddedModel): pass + + +class PlainModel(models.Model): + pass diff --git a/tests/models_/test_routers.py b/tests/models_/test_routers.py new file mode 100644 index 000000000..cec78240c --- /dev/null +++ b/tests/models_/test_routers.py @@ -0,0 +1,20 @@ +from django.test import SimpleTestCase + +from django_mongodb_backend.routers import MongoRouter + + +class TestRouter(SimpleTestCase): + def setUp(self): + self.router = MongoRouter() + + def test_no_model(self): + self.assertIsNone(self.router.allow_migrate("db", "models_")) + + def test_regular_model(self): + self.assertIsNone(self.router.allow_migrate("db", "models_", "plainmodel")) + + def test_nonexistent_model(self): + self.assertIsNone(self.router.allow_migrate("db", "models_", "nonexistentmodel")) + + def test_embedded_model(self): + self.assertIs(self.router.allow_migrate("db", "models_", "embed"), False)