Forums

Postgres: How to configure Django to access DB?

I uploaded a site that is the basic Django "Hello World" site with a few changes. For one thing, the DB is configured to use Postgres. This works fine locally but I am having trouble understanding how to complete the setup on PythonAnywhere.

In the code below, uid's and passwords have been changed. No, the pwd isn't 123456789.

On PA the db was setup using psql as follows:

CREATE DATABASE domain_db;

CREATE USER domain_admin WITH PASSWORD '123456789';

\connect domain_db;

CREATE SCHEMA domain_schema AUTHORIZATION domain_admin;

-- Settings recommended by Django documentation
ALTER ROLE domain_admin SET client_encoding TO 'utf8';
ALTER ROLE domain_admin SET default_transaction_isolation TO 'read committed';
ALTER ROLE domain_admin SET timezone TO 'UTC';

Note that this approach is based on recommendations due to changes to Postgres permissions changes with v15 (which is what we are using locally). I am assuming that this works with v12, which is what I think PA is using. Could be wrong on that.

https://gist.github.com/axelbdt/74898d80ceee51b69a16b575345e8457

https://www.cybertec-postgresql.com/en/error-permission-denied-schema-public/

The project directory structure looks like this:

domain/
    site/
        _config/
            settings/
                base.py           Settings common to local and production
                local.py          Local development settings
                production.py     Production server settings
            asgi.py
            urls.py
            wsgi.py
        staticfiles/
        manage.py
    venv
    .env

In base.py I configure the database using environment variables loaded from the .env file. I have confirmed that the .env file is being loaded and environment variables set according to its contents.

BASE_DIR = Path(__file__).resolve().parent.parent.parent
...
env = environ.Env()
env_file_path = BASE_DIR.parent / ".env"
env.read_env(env_file_path)
...
DATABASES = {
    'default': {
        "ENGINE": env("ENGINE"),
        "OPTIONS": env.json("OPTIONS", default={}),
        "NAME": env("NAME"),
        "USER": env("USER"),
        "PASSWORD": env("PASSWORD"),
        "HOST": env("HOST"),
        "PORT": env("PORT"),
    }
}

Relevant portions of the .env file, again, data changed for this post:

ALLOWED_HOSTS=www.<domain>.com,<domain>.com

# Database
ENGINE=django.db.backends.postgresql
OPTIONS={"options": "-c search_path=domain_schema"}
NAME=domain_db
USER=domain_admin
PASSWORD=123456789
HOST=<prefix>.postgres.pythonanywhere-services.com
PORT=<port provided by PA>

When I try to run makemigrations, I get the following error (edited):

/django/core/management/commands/makemigrations.py:160:

RuntimeWarning: Got an error checking a consistent migration history performed for database connection 'default':

connection failed: connection to server at "xx.xx.xx.xx", port <xxxxx> failed:

FATAL:  password authentication failed for user <user> connection to server at "xx.xx.xx.xx.", port <xxxxx> failed:

FATAL:  password authentication failed for user <user>

I have confirmed the connection using:

psql -h <prefix>.postgres.pythonanywhere-services.com -U domain_admin -d domain_db -p <port>

Not really sure where to go from here. I think the settings in .env are correct. Is there something else I have to setup to make this work? Or, is it a case of Postgres v12 needing a very different configuration with respect of what we are using locally ( v15). If so, is there a way to upgrade to v15 in order to match our production to local?

Thanks.

FATAL: password authentication failed for user <user> means that your username and/or password are incorrect. Either the user you are trying to connect as does not exist or you are using the wrong password for the user.

Thanks for your help.

I am using exactly the same credentials in this command and it works as expected. That's why I am confused. I use exactly the same credentials that are defined in the .env file. What am I missing.

psql -h <prefix>.postgres.pythonanywhere-services.com -U domain_admin -d domain_db -p <port>

I also have debug code at the top of base.py to confirm that the environment variables are set correctly and are being loaded. All checks out.

print(f"SECRET_KEY: {env('SECRET_KEY', default='Not Found')}")
print(f"ALLOWED_HOSTS: {env.list('ALLOWED_HOSTS', default=[])}")
print(f"ENGINE: {env('ENGINE')}")
print(f"OPTIONS: {env('OPTIONS')}")
print(f"NAME: {env('NAME')}")
print(f"USER: {env('USER')}")
print(f"PASSWORD: {env('PASSWORD')}")
print(f"HOST: {env('HOST')}")
print(f"PORT: {env('PORT')}")

Console output

How do you run that debug code?

Anything that will cause base.py to run. For example, python manage.py makemigrations.

One of the things that you are stating above is not true. Perhaps there's a small difference in a username or password or database name between when your using psql vs in django. Perhaps the env variables are not, actually, making it to the DATABASES setting. Perhaps it's something else. We cannot tell because of all of your redactions.

I'll delete the DB and start over, double-checking everything.

I'd be happy to send unredacted screen shots through a private support method. Do you have a ticket system or an email for support?

Yeah you can get support from the email address support@pythonanywhere.com - The response time there might be a bit better also since we only check the forums twice a day