Database config for Django testing - python

I am building an app using Django and Postgres. I managed to do migrations and I want to test it. When I test with sqlite everything works fine, but when I run tests with postgres I'm getting this error:
Creating test database for alias 'default'...
Got an error creating the test database: permission denied to create database
I've checked user's permissions and I'm sure that this user have permission to create database.
My database config looks like this:
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '***',
'USER': '***',
'PASSWORD': '***',
'HOST': '****',
'PORT': '****',
}
}
My postgres db is on a server.
My questions are:
What is the right way to config my db and run tests?
Should I be using sqlite for testing?
If so how my code should look like, so I don't have to comment configs?

It looks like your DB user doesn't have permission to create a new database. Please, take a look here. This command-line utility allows you to create a user and set their permissions.
Example:
createuser my_user --createdb -W --username postgres
Note: you are creating user "my_user" on behalf of PostgreSQL admin role which is postgres by default.
Answering your questions:
You may have several configs for different stages, e.g development, testing, production.
You could use both SQLite and Postgres databases for testing purposes to some extent. You should be awarded, though, if your app relies on some specific features available only in Postgres, then using SQLite for testing doesn't make sense. I personally prefer using the same database for all stages. You could also use docker if you don't want to install DB server on your machine.

Related

Access Django Test Database

I have an API running on Heroku and would like to be able to test it using the test database. My problem I have is that the TestCase setUp(self) method adds the data to an automatically created test database. Then my tests send a POST request to the locally running version of itself. That code then is just using the regular default database instead of the test database the tests are running in.
Here's some code and what I've tried.
In my main settings.py I have named my database like so
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'theOneTrueDB',
}
}
And I read here (https://docs.djangoproject.com/en/3.0/topics/testing/overview/#the-test-database) that
The default test database names are created by prepending test_ to the value of each NAME in DATABASES.
So I figured in my views file for one of my apps I could just do
Tenant.objects.using('test_theOneTrueDB').all() and that would work but it says
django.db.utils.ConnectionDoesNotExist: The connection test_theOneTrueDB doesn't exist
I have also tried
Tenant.objects.using('test_default')
and many other things. I am lost. I would also be okay with setting up another database and then using that in the setup with
Tenant.objects.save(using='theOneTrueDBTest)
or something like that.
Any help would be appreciated!
EDIT:
I know have my settings looking like this
DATABASES = {
'default': {
'NAME': 'theOneTrueDB',
'ENGINE': 'django.db.backends.sqlite3',
},
'other': {
'NAME': 'theOneTrueTest',
'ENGINE': 'django.db.backends.sqlite3',
}
}
but then if I try to save to the other database like this
tempPM.save(using='other')
Then I get this error
AssertionError: Database queries to 'other' are not allowed in this test. Add 'other' to API.tests.TenantLogin.databases to ensure proper test isolation and silence this failure.
You don't need to access the test database directly. It will be used by default and you don't need to worry about it.
By default for sqlite3 backend will be used in-memory database, with the name like this file:memorydb_default?mode=memory&cache=shared,
you can examine the settings while tests are running via:
from django.conf import settings
print(settings.DATABASES)

Django refuse to drop PostgreSQL database [another session using the database]

I try to setup postgresql for django, with the following setting:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'tangorblog_features',
'TEST': {
'NAME': 'tangorblog_features'
}
},
}
The idea is to test using development server with selenium and radish-bdd. I will run the development server, and let selenium and Django LiveServerTestCase to test against that server, without creating a separate database. So each time the test run, the database is reset. But Django refuse that there are other session that using the database.
However when I use mysql with the same settings like:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'tangorblog_features',
'HOST': 'localhost',
'PORT': '',
'USER': 'goat',
'PASSWORD': '',
'TEST': {
'NAME': 'tangorblog_features'
}
},
}
The test runs without a problem, about database being used in another session. I think that this is the PostgreSQL problem. How can I tweak it, so it could behave like MySQL?
this happens because mysql and postgres treat database differently. Mysql database is what postgres calls schema. DROP SCHEMA would also happen quetly, just like https://dev.mysql.com/doc/refman/5.7/en/drop-database.html DROP SCHEMA in mysql:
DROP SCHEMA is a synonym for DROP DATABASE.
Differently for postgres you connect to the database to work with schemas, so if smbd wants to drop database you have terminate their sessions. Not like in mysql
Dropping a database does not remove any TEMPORARY tables that were
created in that database. TEMPORARY tables are automatically removed
when the session that created them ends.
which means session is not aborted on database drop.
In order to force database drop and regarding the fact
...it cannot be executed while you or anyone else are connected to the
target database
you have to terminate accordiing backends first, you can do it with
select pg_terminate_backend(pid)
from pg_stat_activity
where datname = 'tangorblog_features';
Of course you have to be connected to some other db yourself

Using remote MySQL database on Heroku running Django app

I've been struggling with the following problem:
I have a MySQL database running on a remote web host. I connect to the MySQL database in my Django app (I use it as the main database). The Django app is running on a Heroku server but I get different data results compared to running it locally.
Am I missing something, or are changes done on Heroku not committed to the database?
MySQL settings:
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'xxx',
'PASSWORD': 'xxx',
'HOST': 'xxx',
'PORT': 'xxx',
}
}
I just see that if you delete the ad-on provided by heroku, it will use the DB you put on the settings of your project
I believe Juan Carlos Hernández is correct. To expand on his answer, Heroku uses it's own database instance, unless you tell it otherwise by pointing the DATABASE_URL to the one you would like to use. Please note that Heroku will prevent you from overwriting the DATABASE_URL in use since that will destroy the existing database. Although tagged as ruby-on-rails, the answers I found here seem relevant.
To summarize, you just have to run
heroku config:add DATABASE_URL=mysql://dbusername:dbpassword#databasehostIP:3306/databasename
heroku config:add SHARED_DATABASE_URL=mysql://dbusername:dbpassword#databasehostIP:3306/databasename
Then do
heroku restart
Or you can change these variables in the Heroku panel.

How to copy all the data from main server database to the local sqlite database to use locally?

Local database setting-
`DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}`
main database setting-
`DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql',
'NAME': '******',
'USER': '******',
'PASSWORD': '********',
'HOST': '******',
'PORT': '****',
}
}`
I did it from the git project
python manage.py dumpdata > all.json . But then I don't know what to do next like how to use this json file to update local database by which commands.
I am very beginner to this. kindly help me solve this problem.
You should always use an RDBMS from the same vendor at both ends. And preferably the same version. Though ORMs such as Django's are supposed to be database agnostic, there are still many subtle differences between different vendor's products. Sqlite for example is the least feature complete of the popular open source databases. If you use sqlite in development, and postgresql in production, you are limiting yourself to the set of features that sqlite has. But postgresql has many more. Right end of sermon.
At the live server do
python manage.py dumpdata > data.json
Then copy the file over to the local machine and do:
python manage.py loaddata data.json
python manage.py migrate
python manage.py loaddata all.json
this command will load entire data to database whatever you specified in settings.py

Testing Django app with Postgis Backend

I'm attempting to run tests on a GIS Django application running PostGIS as a database backend.
When I attempt to run tests, I get the following error:
django.db.utils.ProgrammingError: permission denied to create extension "postgis"
HINT: Must be superuser to create this extension.
The error makes sense. Only admin database users can install extensions since this privilege allows the execution of arbitrary external code. BUT since the test runner has to re-create the database each time the tests are run, Django's database user can't proceed.
Here is my database configuration.
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'my_db',
'USER': 'my_user',
'PASSWORD': 'my_crazy_secure_password',
'HOST': '127.0.0.1',
'PORT': '',
'TEST_NAME': 'test_my_db',
},
}
My solution to this was surprisingly simple, once I figured it out.
Connect to the template1 database, and run CREATE EXTENSION IF NOT EXISTS postgis;. The template1 database is copied when a new database is created, so all new databases will already have the extension installed.

Categories

Resources