django - specify database for TestCase fixtures - django

I have two databases that my site uses and I have an app that uses both of them. I need to write a TestCase that loads fixtures for both databases. I use a DB router, which works fine in production, but in the testing framework, Django insists on using the 'default' database for all fixtures, even for models that specify the other database. How do I tell Django to run a fixture against another database?
My TestCase is defined list:
class VerifierTestCase(TestCase):
fixtures = ['zipcodes_test.json', 'all_states.json', 'wtf.json']
multi_db = True

There is actually a bug in Django that causes it to ignore the name-based db-specific pointers if you specify the entire fixture name.
so if you do fixtures = ["mydata.default.yaml", "mydata.myotherdatabase.yaml"]
It will load both fixtures into the default database.
But if you do fixtures = ['mydata']
It will load correctly. This is also true for dbengine specific filenames (e.g. mydata.default.postgresql.sql) as well.

Fixtures are targeted at specific databases by filename. This is true in TestCase instances as well, as they just call the loaddata command.
See https://docs.djangoproject.com/en/dev/ref/django-admin/#database-specific-fixtures

If you have a multi-db setup with models exclusive to each database. You need to save a fixture file for each database (with the non-applicable database files being empty).
If your code defines fixtures = ["sample"] and you have two databases default and other.
You need two files: sample.default.json and sample.other.json. If sample contains only models from db default, sample.other.json will be an empty file ([]) and vice-versa.
Tried with Django 3.2

Related

Detect database DDL schema changes with Django

Let's say that we have a Django app that looks on a legacy database.
If someone make changes on some database tables from a db client as DBeaver for example and not through Django models, is there a way to identify these changes?
You can do in a terminal, inside your Django project directory : python manage.py inspectdb > models.py
You will have models related to your tables.
By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion.
If you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option above to True (or remove it because True is its default value).

Django Test with default database and without running any migrations

Is there any way I can use my default local database for testing in Django 1.9. I also don't want to run any migrations, and I want to test it locally.
The reason I want to do it this way is that in my migrations, I have a data migration referring to some entry from a model and when tests run and create a test_database the migrations fail as there are no entries in the test model and this data migration use .get()
I don't know how I should resolve this issue. The best way I could think of is my default database for testing.

Connecting and importing models from multiple database connections Django

In a django app, I have two postgresql databases connected through settings.py: one is default and other is AppDb. AppDb is placed on a remote machine.
I want to query from a 'Courses' model from AppDb using 'using()' and 'Courses' model is not available in default database.
So my query goes like this:
courseInfo = Courses.objects.using('AppDb').filter(cuser_id = 12)
But I am getting NameError for 'Courses'
Can I have a solution for such queries without using routers
If you have an existing database, you still need to create an app and models for that database in order to use the ORM.
To help you create the model classes, you can use the inspectdb management command which will try to guess the models from an existing database and create the models.py for you. Its not perfect, but it will save you some time.
You will still have to make sure the models have a primary key and are written in the correct order (so that foreign keys will work correctly).

Django unittests - ImproperlyConfigured error

Im trying to write tests for my module. When i run:
python manage.py test my_module
Im getting message:
django.core.exceptions.ImproperlyConfigured: Please fill out the database NAME in the settings module before using the database.
I dont have any test yet, just BaseTest where im creating users, groups and assigning permissions.
Where could be the problem? Server normally works, configuration seems to be good. Do i need to define settings for test?
Ok. I think i know what was the problem :] I had lists with permissions stored in other module. So i were writting from module.perms import perms (normal python list). Its seems, that python is doing something more than just import that list from other module to my module. And that was the cause of failing.
Solution:
Surround code after list definition with:
if __name__ == "__main__":
...
Then everything should be working good.
Ok. I think i know what was the problem :] I had lists with permissions stored in other module. So i were writting from module.perms import perms (normal python list). Its seems, that python is doing something more than just import that list from other module to my module. And that was the cause of failing.
Solution: Surround code after list definition with:
if __name__ == "__main__":
...
Then everything should be working good.
You need to have your DATABASE setting in place in settings.py, and your app needs to be in installed apps. For example:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'database.sqlite',
python manage.py test doesn't use the NAME database defined in settings.py DATABASES. From the docs -
Tests that require a database (namely, model tests) will not use your
"real" (production) database. Separate, blank databases are created
for the tests.
Regardless of whether the tests pass or fail, the test databases are
destroyed when all the tests have been executed.
By default the test databases get their names by prepending test_ to
the value of the NAME settings for the databases defined in DATABASES.
When using the SQLite database engine the tests will by default use an
in-memory database (i.e., the database will be created in memory,
bypassing the filesystem entirely!). If you want to use a different
database name, specify TEST_NAME in the dictionary for any given
database in DATABASES.
To answer your question. You can define a test database with the TEST_NAME setting. But you shouldn't have to.
Here's another potential solution for people finding this through search:
I was trying to define my own TestRunner class inside my settings file, which meant it had to import DjangoTestSuiteRunner. This import at the top of the file caused the ImproperlyConfigured error. Moving the custom TestRunner class to a separate file resolved the issue.

Django - Why doesn't syncdb respect the database router?

I have set up a database router to direct different apps and different models to different databases using the db_for_read and db_for_write router methods.
That works very well, except that ./manage.py syncdb does't respect those router settings.
When I syncdb my models, all of them are created in the default database.
The database router only provides an allow_syncdb method, but no sync_to method. Is there a way to tell the syncdb command where to create the new tables?
Note: I can't use the --database feature, as sometimes some of the model apps go to a different database than the rest of the app.
When you write your router make sure you've written the allow_syncdb() method. It takes both a database and a model. When you run manage.py syncdb you're essentially setting the --database=default. If you don't want your models to sync to the default database then your allow_syncdb() method should return False for the condition that db==default and model._meta.app_label==myapp.
You'll need to run syncdb with the --database=your_other_db option to get myapp into that db. But make sure in that case that allow_syncdb() returns True only for the case that db==your_other_db and model._meta.app_label==myapp.
Does that make sense? Basically you have to run the manage.py syncdb method twice, once for each database. You cannot run it only once and have it update both databases.