Cheknov
Cheknov

Reputation: 2082

How to change Django project settings.py dynamically for production and staging servers

In my current project, I have two servers: production and staging.

The staging server uses the default MySQL Django connector.

The production server uses a custom connector for MariaDB.

The information from the database is retrieved through raw queries. I can't use ORM for this project.

Both staging and production are connected to the project's git repository.

If I push a commit with the specific settings for the staging server, when I git pull from production server it won't work and vice versa.

I need to create a mechanism that detects if the server is production or staging and based on that it executes the specific code for MariaDB or MySQL.

The conflicting files are: settings.py (no explanations needed) and db.py (contains all the logic of the database, here are implemented the functions that are responsible for making queries to the database).

STAGING SERVER

db.py (truncated):

#!/usr/bin/python
from django.db import connection
import re
from collections import namedtuple

def get_genome_id_from_start_value(start):
    results = []
    cursor = connection.cursor()
    cursor.execute("SELECT record_id FROM `db-dummy`.g_info WHERE start = %s", ('{}%'.format(start),))
    columns = [column[0] for column in cursor.description]
    results = []
    for row in cursor.fetchall():
        results.append(dict(zip(columns, row)))
    return results[0]['record_id']

settings.py (truncated):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db-dummy',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': '127.0.0.1',
        'PORT': '',
        'TIME_ZONE': 'UTC',
    }
}

PROD SERVER

db.py (truncated)

#!/usr/bin/python
import mariadb 
import re
from collections import namedtuple

def get_genome_id_from_start_value(start):
    conn = mariadb.connect(
        user="user",
        password="password",
        host="localhost",
        database="db-dummy")
    results = []
    cursor = conn.cursor(named_tuple=True)
    try:
        cursor.execute("SELECT record_id FROM `db-dummy`.g_info WHERE start = ?", (start,))
        columns = [column[0] for column in cursor.description]
        results = []
        for row in cursor.fetchall():
            results.append(dict(zip(columns, row)))
        return results[0]['record_id']
    except mariadb.Error as e:
        print(f"Error: {e}")

settings.py (truncated):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

What I have tried:

settings.py:

STAGING = 'staging'
PROD = 'prod'

if socket.gethostname().startswith('ip-177-77-7-777'):
    DJANGO_HOST = STAGING
else:
    DJANGO_HOST = PROD

if PROD == DJANGO_HOST:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'db-dummy',
            'USER': 'user',
            'PASSWORD': 'password',
            'HOST': '127.0.0.1',
            'PORT': '',
            'TIME_ZONE': 'UTC',
        }
    }

I think that will work for settings.py but now I need a solution for db.py.

Any suggestions?

Upvotes: 0

Views: 362

Answers (1)

Jisson
Jisson

Reputation: 3725

Quick Solution, Create a common function which returns cursor, for production it will return a cursor for production and for statging it return a cusror for staging and use this cursor in get_genome_id_from_start_value.

from django.conf import settings
    def get_cursor():
        if settings.PROD == settings.DJANGO_HOST:
            conn = mariadb.connect(
            user="user",
            password="password",
            host="localhost",
            database="db-dummy")
        return conn.cursor(named_tuple=True)
        else:
           return cursor = connection.cursor()
    def get_genome_id_from_start_value():
       cursor  = get_cursor()
       ----

One better way to use django_environ, then you can define the evironment sepecfic constants, databases to a file and can these values in python files https://pypi.org/project/django-environ/

.env
DJANGO_HOST=PROD
DEBUG=false
----

.env
DJANGO_HOST=STAGING
DEBUG=on
-----

settings.py
environ.Env.read_env()
env = environ.Env(DEBUG=(bool, False))
DEBUG = env('DEBUG')
DJANGO_HOST = env('DJANGO_HOST')

Upvotes: 1

Related Questions