I am using utf-8 general case insensitive for for mysql database, but django creates a test db with latin collation
I have set this:
TEST_CHARSET="utf8_general_ci"
TEST_COLLATION="utf8_general_ci"
In the settings file, but to no avail.
What else should i do?
TEST_CHARSET and TEST_COLLATION are renamed to CHARSET and COLLATION and moved to TEST dictionary in Django 1.8:
DATABASES = {
...
'TEST': {
'CHARSET': 'utf8',
'COLLATION': 'utf8_general_ci',
}
}
in settings add:
DATABASES = {
'default': {
...
'TEST_CHARSET': "utf8",
'TEST_COLLATION': "utf8_general_ci",
}
}
Please see here: https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-DATABASE-TEST
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': <db_name>,
'USER': <user>,
'PASSWORD': <password>,
'HOST': <host>,
'PORT': <port>,
'TEST': {
'NAME': <test_db_name>,
'CHARSET': 'utf8',
'COLLATION': 'utf8_general_ci',
},
},
}
I had the same problem and spent hours of figuring it out until noticed that
TEST_CHARSET
TEST_COLLATION
should be a part of the DATABASES, not settings.py.
It's very easy to mix them up...
https://docs.djangoproject.com/en/dev/ref/settings/#testing
As others have pointed out, you need something like this to create the database
DATABASES = {
...
'TEST': {
'CHARSET': 'utf8mb4',
'COLLATION': 'utf8mb4_unicode_ci',
}
}
But you also will want to make sure that you have something like this as well, to make sure that your tests communicate with the db with the appropriate charset.
DATABASES = {
...
'OPTIONS': {
'charset': 'utf8mb4'
}
}
Take a look at the settings file example here: https://docs.djangoproject.com/en/dev/ref/databases/#connecting-to-the-database
Related
I want to keep my unit test database completely separate from other environments including using different user credentials. This is mostly to prevent anyone from unintentionally running unit tests against the development database and mangling the dev data or wiping it out entirely if the --keepdb option isn't specified. The code below detects the "test" in the sys args and this seems to work but is very clunky. If I'm missing a better way to do this please advise.
I have separate settings files for each environment so this will only be on the development server where the unit tests are run automatically and won't end up on any production servers.
Environment:
Django 1.11
Python 3.4.x
MariaDB
# this works but is clunky
import sys
if 'test' in sys.argv:
DATABASES = { # test db and user
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db_test',
'USER': 'test_user',
'PASSWORD': 'secretpassword',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': { # redundant but explicit!
'NAME':'dev_db_test',
},
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db',
'USER': 'dev_db_user',
'PASSWORD': 'dev_password',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': {
'NAME':'dev_db_test', # redundant but explicit!
},
}
}
I'd like to do this but unfortunately Django doesn't look at the TEST credentials
# cleaner approach but doesn't work - don't do this!
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db',
'USER': 'dev_db_user',
'PASSWORD': 'dev_password',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': {
'NAME':'dev_db_test', # Django uses the test db NAME
'USER':'test_user_ignored', # but ignores the USER and PASSWORD
'PASSWORD':'ignoredpassword',
},
}
}
Would something like this work for your situation?
import sys
if 'test' in sys.argv:
NAME = 'dev_db_test'
USER = 'test_user'
PASSWORD ='secretpassword'
else:
NAME = 'dev_db'
USER = 'dev_db_user'
PASSWORD ='dev_password'
DATABASES ={ # test db and user
'default':
{
'ENGINE': 'django.db.backends.mysql',
'NAME': NAME,
'USER': USER,
'PASSWORD': PASSWORD,
'HOST': 'the-db-host',
'PORT': '3306',
'TEST':
{ # redundant but explicit!
'NAME':'dev_db_test',
},
}
}
print(DATABASES)
AFAIK, you don't need to create a separate test database if you want to run unit tests over it. Here is the documentation link of test database.
It states that:
Tests that require a database (namely, model tests) will not use your “real” (production) database.
Separate, blank databases are created for the tests.
You can follow this link to write your tests and it will not affect your production or development database.
I'm using a database URL string in my settings like:
DATABASES = {
'default': "mysql://root:#localhost:3306/mydb"
}
When I migrate I get this warning:
MySQL Strict Mode is not set for database connection 'default'
Now my question: How can I combine the two things?
I cannot use the "regular" way to set the database settings with a dictionary because my database url comes from an environment variable.
Thx in advance!
You could update your settings afterwards:
DATABASES['default']['OPTIONS'] = {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"}
I think this one will help you.
you can pass the options as a query string in the URL
DATABASES = {
'default': dj_database_url.config(default="mssql://USER:PASSWORD#HOST:PORT/NAME?init_command=SET sql_mode='STRICT_TRANS_TABLES'&charset=utf8mb4", conn_max_age=500)
}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': 'root',
'PASSWORD': 'test123',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4',
}
}
}
Try to give init_command of database options in settings.py
If want know more refer the docs django_mysql.W001: Strict Mode
In my project I am using multiple databases, 3 to be precise.
One default and two reference databases (another host), which are powered and updated by our data team. I am using 4 tables from 2 external databases, which were inspected with ./manage.py inspectdb. They are set to managed=False
Everything works fine, my application works as expected and planned.
Now the fun begins, I need to write tests. I do not want to delete my databases.
I need to read from them, I do not want to create fixtures.
Every time when I try to use pytest or custom django tests, it is trying to delete my databases, recreate, run migrations and stuff.
How can I preserve that ? Either in pytest or django tests ? I've tried to --re-usedb, and couple of another params.
This is my database settings (parts which can be uploaded)
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'default_db',
'USER': 'default_usr',
'PASSWORD': 'default_pass',
'HOST': 'postgres.somehost.com',
'SUPPORTS_TRANSACTIONS': True,
},
'geolocations': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=some_schema'
},
'NAME': 'geo_name',
'USER': 'geo_user',
'PASSWORD': 'geo_password',
'HOST': 'some-host.domain.com',
'SUPPORTS_TRANSACTIONS': True,
},
'eoc': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=another_schema'
},
'NAME': 'eco_name',
'USER': 'eoc_user',
'PASSWORD': 'eoc_',
'HOST': 'some-another-host.domain.com',
'SUPPORTS_TRANSACTIONS': True,
}
}
So inside of pytest.ini you should be able to add a '--no-migrations' flag in order to ensure that migrations are not being made. Using a pytest marker pytest documentation should enable you to have access to your database.
The mark you need is:
pytestmark = pytest.mark.django_db
I tried setting
DATABASES = {
'default': {
'NAME': 'db',
'ENGINE': 'mysql.connector.django',
'USER': 'dbuser',
'PASSWORD': 'dbpass',
'OPTIONS': {
'autocommit': True,
'init_command' : 'SET storage_engine=INNODB',
},
}
}
(UPD: updated the above code so ppl won't get confused that I am not using django settings the right way)
in Django settings, but this backend doesn't accept such connection option...
http://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html
is there any other way of doing this?
First, to use MySQL Connector/Python Django backend, you have to set the ENGINE setting to mysql.connector.django:
DATABASE = {
'default': {
..
'ENGINE': 'mysql.connector.django',
..
}
}
Indeed, MySQL Connector/Python does not have the init_command connection argument. I can see value in adding an option for setting the default storage engine in the Django OPTIONS though. If you really want it, I would suggest opening a feature request on http://bugs.mysql.com.
Small note that MySQL 5.6 (and if you start out, you should use this version) has storage engine set to InnoDB by default.
You need to set the entire setting:
DATABASES = {
'default': {
'NAME': "MyDatabaseName,
'ENGINE': 'django.db.backends.mysql',
'USER': "MyUsername",
'PASSWORD': "MyPassword",
'HOST': "MyHostName",
'OPTIONS': {'init_command': 'SET storage_engine=INNODB'},
}
}
Does anyone kno how to use a specific database for a single test in Django?
EDIT: At the moment, i'm using sqlite for testing, but, i want to use a mysql database for a specific test (def test_benchmark...), which will benchmark some sql statements.
Thanks
I don't know of any builtin way to do it - but I didn't look for it neither honestly. One possible (dirty) hack is to check what's in sys.argv in your settings (which is just another Python module) and have an alternate database settings for your particular test, ie:
# settings.py
import os, sys
DATABASES = {
'default': {
'NAME': 'db_name',
'ENGINE': 'your.engine',
'HOST': 'server',
'USER': 'django',
'PASSWORD': 'django',
}
}
if "test" in sys.argv and "your-test-name" in sys.argv:
DATABASES = {
'default': {
'NAME': 'other_db_name',
'ENGINE': 'your.engine',
'HOST': 'server',
'USER': 'django',
'PASSWORD': 'django',
}
}
In Django you set the database in your settings.py file. The configuration should look something like this:
DATABASES = {
'default': {
'NAME': 'db_name',
'ENGINE': 'sql_server.pyodbc',
'HOST': 'server',
'USER': 'django',
'PASSWORD': 'django',
'OPTIONS' : { "use_mars" : False,
"provider" : "SQLNCLI10",
"extra_params" : "MARS Connection=True"},
}
}