Create a separate clean database for tests in django - django

Hi I would like to create a separate empty database for tests. I read on django docs (https://docs.djangoproject.com/en/2.1/topics/testing/overview/)
that :
The default test database names are created by prepending test_ to the value of each NAME in DATABASES. When using SQLite, the tests will use an in-memory database by default (i.e., the database will be created in memory, bypassing the filesystem entirely!). The TEST dictionary in DATABASES offers a number of settings to configure your test database. For example, if you want to use a different database name, specify NAME in the TEST dictionary for any given database in DATABASES.
So I tried:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'test_db': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'test_db.sqlite3'),
}
}
but tests still use the default database when running them with
./manage.py test
How can I create and specify a new, empty database for tests purposes?

I think you misread the documentation. Django automatically uses a separate database.
Say your config file looks like:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Then Django will not use the 'default' database, if the name of the database is 'FOO', it will create a database with the name test_FOO. Such that testing and running the Django project should - without of course "patching" this behaviour - not interfere (at least not the databases).
If you however want to specify a different NAME (or other attributes), you can add a 'TEST' key [Django-doc] in the databases, like:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'TEST': {
'NAME': os.path.join(BASE_DIR, 'other_db.sqlite3'),
}
}
}

Related

Sync all tables from sqlite to postgres

I have a django application and deployed it on DigitalOcean. But the only problem is, new models, admin models, tables are not showing in django admin dashboard which is on running on server. Although I pushed al changes to github, pulled them from, and made migrations, again nothing changes. How can migrate all tables from db.sqlite3 to postgresql ?
I would bet your settings.py database is still configured to the default sqlite.
# default settings.py using SQLlite
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Change that to your actual postgresql database address
Since you're deploying, it is best practice to configure those parameters as separate environnment variables, as such in your settings.py. Environnment variables would then have the actual values.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['POSTGRE_NAME'],
'USER': os.environ['POSTGRE_USER'],
'PASSWORD': os.environ['POSTGRE_PASSWORD'],
'HOST': os.environ['POSTGRE_HOST'],
'PORT': os.environ['POSTGRE_PORT'],
}
}

django pick from multiple databases for testing

I have multiple databases defined. This is for test profile, and I want to be able to specify which database to be picked for testing. eg: "python manage.py test -db=mysql"
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'mysql': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysql_test',
}
}
I went through the django documentation, but i cant find a clear cut way of doing it. One way of getting around this is setting up environment variables, and define both databases as default. Then use the db based on the database type.
please let me know if there is a much better way of doing this.
thanks
Amal
You can use the TEST attribute of DATABASES:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'TEST': {
'NAME' : 'mysql'
},
},
'mysql': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysql_test',
}
}
but is there a reason you don't want to use the default test database django creates?

Force django to create tables using MYISAM storage engine

How to force django to use MYISAM storage engine when creating database using syncdb command? This page does not help much to shed light in this issue.
MYISAM is the perfect choice since the database is almost only used for reading and MYISAM is significantly faster that InnoDB. There are still some models.ForeignKey fields in the model, but they are only being used to create master detail admin pages. There is not need of having the actual foreign keys in the database.
See this page. Using an OPTIONS variable in your DATABASES setting should do the trick, but migrating an existing database to a new engine isn't so easy (think you'd have to re-initialize).
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '',
'USER': '',
'PASSWORD': '',
'OPTIONS': {
"init_command": "SET storage_engine=MYISAM",
}
}
}
You should set the storage engine as INNODB in the database definition directly, like this.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
.....
'STORAGE_ENGINE': 'MYISAM'
}
}
For New Version you can use:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
.....
'OPTIONS': {
"init_command": "SET storage_engine=MYISAM",
}
}
}

How to switch django database before I login in admin?

I face a problem that I design a information system base on django-admin.
But I have several independent system to build.every system's Features are all the same.
So I want to put a texbox to select to switch my database before I login in admin.How can I do that?
for example ,when I want to login in admin,I want to freely switch from db1 to db2 or reverse.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
},
'newData': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
}
}

Different db for testing in Django?

DATABASES = {
# 'default': {
# 'ENGINE': 'postgresql_psycopg2',
# ...
# }
# for unit tests
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase'
}
}
I have two databases: one I'd like to use for unit tests, and one for everything else. Is it possible to configure this in Django 1.2.4?
(The reason I ask is because with postgresql I'm getting the following error:
foo#bar:~/path/$ python manage.py test
Creating test database 'default'...
Got an error creating the test database: permission denied to create database
Type 'yes' if you would like to try deleting the test database 'test_baz', or 'no' to cancel: yes
Destroying old test database...
Got an error recreating the test database: database "test_baz" does not exist
Why could I be getting this error? I guess I don't really care if I can always use SQLite for unit tests, as that works fine.)
In your settings.py (or local_settings.py):
import sys
if 'test' in sys.argv:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase'
}
The way I handle this is through having multiple settings files, since I use that to maintain a set of common settings with modifications for each instance. It's a little more complicated to set up than some of the other solutions, but I needed to do it anyway because I was managing slightly different settings for local development, remote development, staging and production.
https://code.djangoproject.com/wiki/SplitSettings has a number of options for managing settings, and I've chosen a practice similar to the one described at https://code.djangoproject.com/wiki/SplitSettings#SimplePackageOrganizationforEnvironments
So, in my Django project directory, I have a settings folder that looks like this:
$ tree settings
settings
├── defaults.py
├── dev.py
├── dev.pyc
├── __init__.py
├── lettuce.py
├── travis.py
├── unittest.py
The common settings are in settings/defaults.py and I import these in my instance settings files. So settings/unittest.py looks like this:
from defaults import *
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'my_database',
}
}
Then, when I want to run tests, I just execute:
$ ./manage.py test --settings=settings.unittest
to use sqlite for testing. I'll use a different settings module if I want to use a different test runner or database configuration.
You can specify test database in settings.py. See
https://docs.djangoproject.com/en/3.0/topics/testing/overview/#the-test-database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'USER': 'mydatabaseuser',
'NAME': 'mydatabase',
'TEST': {
'NAME': 'mytestdatabase',
},
},
}
I solved this issue simply creating other settings constant DATABASES_AVAILABLE.
DATABASES_AVAILABLE = {
'main': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'nep',
'USER': 'user',
'PASSWORD': 'passwd',
'HOST': 'localhost',
},
'remote': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'nes_dev',
'USER': 'usr',
'PASSWORD': 'passwd',
'HOST': '200.144.254.136',
},
'sqlite': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
}
# This solves the problem with tests
# Define a system variable called DJANGO_DATABASE_TEST and set it to the
# the database you want
database = os.environ.get('DJANGO_DATABASE_TEST', 'main')
DATABASES = {
'default': DATABASES_AVAILABLE[database]
}
This accelerated dramatically test execution.
import sys
if 'test' in sys.argv:
DATABASES['default'] = {
'ENGINE': 'django.db.backends.sqlite3',
'TEST_CHARSET': 'UTF8', # if your normal db is utf8
'NAME': ':memory:', # in memory
'TEST_NAME': ':memory:', # in memory
}
DEBUG = False # might accelerate a bit
TEMPLATE_DEBUG = False
from django.core.management import call_command
call_command('syncdb', migrate=True) # tables don't get created automatically for me
Though this is already solved...
If your database for tests is just a normal DB:
I think you are not doing unit test since you rely in the database. Anyway, django contains a test type for that (not unitary): django.test.TestCase
You need to derive from django.test.TestCase instead of unittest.TestCase that will create a fresh rehershal database for you that will be destroyed when the test end.
There are interesting explanations/tips about testing with db in the following link
Testing Django Applications
If you have access to manually create the database, you could use django-nose as your TEST_RUNNER. Once installed, if you pass the following environment variable, it will not delete and re-create the database.
REUSE_DB=1 ./manage.py test
You can also add the following to settings.py so you don't have to write REUSE_DB=1 every time you want to run tests:
os.environ['REUSE_DB'] = "1"
Note: this will also leave all your tables in the databases which means test setup will be a little quicker, but you will have to manually update the tables (or delete and re-create the database yourself) when you change your models.
You can mirror your db by editing settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'USER': 'mydatabaseuser',
'NAME': 'mydatabase',
'TEST': {
'MIRROR': 'default',
},
},
}
Why could I be getting this error?
Because of insufficient permissions. You can alter the user permissions by ALTER USER username CREATEDB; after running psql with superuser priviliges.
Example,
$ sudo su - postgres
$ psql
psql (9.3.18)
Type "help" for help.
postgres=# ALTER USER username CREATEDB;
ALTER ROLE
I had your same issue. I resolved it just adding in settings.py the TEST value in the database, available in my Django version 4.0.2, in this way:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'HOST': host,
'NAME': name,
'TEST': {'NAME': 'test_db'},
'USER': user,
'PASSWORD': your_password,
}
}.
This temporary creates db with different name and the conflict is resolved.