Can't reference Django database with dj_database_url - python

I have a Django application using decouple and dj_database_url (it is not on Heroku). If I put my connection information in settings.ini (DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, and DB_PORT) and set up my database connection in settings.py like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': 'DB_PORT',
}
}
It works fine.
However, if I put this in my settings.ini:
DATABASE_URL=postgres://johndoe:mypassword#123.456.789.000:5000/blog_db
and reference it like this in my settings.py:
DATABASES = {"default": dj_database_url.config(default=config("DATABASE_URL"))}
It doesn't work. I just get a 500 when I try to run my server. I presume there is something wrong with my syntax. Can anyone point out what I'm doing wrong?
Thanks!

Related

Trouble hooking up postgres to django

Following the documentation from Django Postgres DocumentationI added to my settings.py
in settings I set
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'OPTIONS': {
'service': 'my_service',
'passfile': '.my_pgpass',
},
}
}
Adjacent to settings.py I created pg_service.conf with
[my_service]
host=localhost
user=USER
dbname=NAME
port=5432
and adjacent to that I created mypg_pass
localhost:5432:PostgreSQL 14:postgres:LetMeIn
I am pretty sure I followed the documentation but on python manage.py check I got the following error.
connection = Database.connect(**conn_params)
File "C:\Users\oliver\base\correlator2v2\correlator2home\venv\lib\site-packages\psycopg2\__init__.py", line 122, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)django.db.utils.OperationalError: definition of service "my_service" not found
It is not able to find the service, but actually one is not required to use the service at all...
OP can simply
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'NAME', # database name
'USER': 'USER',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}
}
Adjacent to settings.py I created pg_service.conf
That is not where the system looks for it, see the docs
"By default, the per-user service file is named ~/.pg_service.conf." Where ~ refers to your home directory, not your current directory (and surely doesn't refer to 'the same directory where settings.py is located', since PostgreSQL doesn't even know what that file is)

Django test with different database user

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.

Running two databases on heroku with django

I have two databases that my Django application needs access. One is a shared database owned by a separate app with the Django app only having read access. The second is entirely owned by the Django app.
For local development I am ok but I'm not sure how to configure things so that Heroku uses the second database.
Currently I have the shared database promoted to DATABASE_URL and the secondary database is at HEROKU_POSTGRESQL_BLUE_URL.
In my settings I have:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'main_database_name',
'USER': 'username',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}, 'secondary': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'secondary_database_name',
'USER': 'username',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}
}
Please ask any more questions if you need me to clarify.
Thanks!
In summary, my specific problem is: I don't know how to have Heroku use the HEROKU_POSTGRESQL_BLUE_URL as the "secondary" database.
---Edit----
At the bottom of settings.py:
# Configure Django App for Heroku.
import django_heroku
django_heroku.settings(locals())
This is where the connection is made between my app's default database and Heroku's DATABASE_URL. I still haven't solved the issue but after some troubleshooting help in the comments, I believe the answer will be found in there.
Here is my working solution.
I have a local_settings.py file not tracked by version control. This contains the database settings for the developer's postgres instance.
local_settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'main_database_name',
'USER': 'username',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}, 'secondary': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'secondary_database_name',
'USER': 'username',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}
}
Then in settings.py I try to import the local_settings.py file. If it doesn't exist, I use the django_heroku package to configure everything for Heroku. In my case, I need to pass the keyword argument databases=False since I want to do a more custom configuration for the databases.
settings.py (only the relevant parts)
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
# These database settings are used for heroku deployments. They are overwritten with local_settings.py in development.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DATABASE_URL'),
'USER': '',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}, 'secondary': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('SECONDARY_DATABASE_URL'),
'USER': '',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '5432',
}
}
try:
from local_settings import *
except ImportError as e:
# Configure Django App for Heroku.
import django_heroku
django_heroku.settings(locals(), databases=False)
In order for this to work you would need to set the Heroku env variable SECONDARY_DATABASE_NAME to the url of your database.
To find out the URL of your secondary database run heroku config -a your_app_name. Copy the url and then set a new environment param in heroku by running
heroku config:set SECONDARY_DATABASE_URL=postgres://xxxxxxx -a your_app_Name
There are a lot of choices with how you would handle the ENV variables, I liked this because I can just set it in my staging and production environments and the same settings work for both.

django - MySQL strict mode with database url in settings

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

Django migrate tables to new database

I originally had a django project with a single app and all models were defined in that app. The project, when initiated only used the default database. It has now become an unwieldy app that I'm trying to break down into smaller apps. Doing so, I want to use different databases for the different apps. I've setup new databases and a router in the settings.py file. However, I'm confused about how to migrate existing tables to the new databases.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name',
'USER': 'db_user_name',
'PASSWORD': 'password',
'HOST': 'hostname',
'PORT': '3306',
},
'db2': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name2',
'USER': 'db_user_name2',
'PASSWORD': 'password2',
'HOST': 'hostname2',
'PORT': '3306',
}
}
I would want an app (e.g. app1) to be moved from default to db2. The router already knows to specify app1 to db2 but running migrations is doing nothing. Any ideas?
#knbk's answer was ultimately correct, except that the solution involved an additional step.
1. python manage.py migrate auth --database=db2
2. python manage.py migrate app1 --database=db2

Categories

Resources