Search code examples
pythonsql-serverdjangoescaping

Database config for Django and SQL Server - escaping the host


I have setup my Django app to use Microsoft SQL Server database. This is my database config.

 DATABASES = {
    'default': {
        'ENGINE': 'mssql',
        'NAME': "reporting",
        'HOST': '192.168.192.225\SQL2022;',
        'PORT': 1433,
        'USER': "sa",
        'PASSWORD': "Root_1421",
        'OPTIONS': {
            'driver': 'ODBC Driver 17 for SQL Server',
        },
    }
}

The SQL Server database is installed on my desktop machine and DESKTOP-RC52TD0\SQL2022 is the host\instance name. When print my config, I get the following.

{'default': {'ENGINE': 'mssql', 'NAME': 'reporting', 'HOST': 'DESKTOP-RC52TD0\\SQL2022', 'USER': 'sa', 'PASSWORD': 'Root_1421', 'OPTIONS': {'driver': 'ODBC Driver 17 for SQL Server'}}}

Notice that in HOST, the value has two slashes added to it, which is causing my app to not be able to connect to the database. I believe this is because of Python escaping feature for strings. How do can I escape so that I end up with a single slash and not double? As I am getting the following error:

django.db.utils.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

I've tried the following and still same result:

  1. r'DESKTOP-RC52TD0\SQL2022'
  2. 'DESKTOP-RC52TD0\\SQL2022'
  3. r'DESKTOP-RC52TD0\SQL2022'

Any ideas how I can escape in the context of a dictionary. In a string adding double slash \\ works but not when used in a dictionary.

I am running the app using docker-compose.

version: '3'

services:
  # sqlserver:
  #   image: mcr.microsoft.com/mssql/server
  #   hostname: 'sqlserver'
  #   environment:
  #     ACCEPT_EULA: 'Y'
  #     MSSQL_SA_PASSWORD: 'P@55w0rd'
  #   ports:
  #     - '1433:1433'
  #   volumes:
  #     - sqlserver-data:/var/opt/mssql
  web:
    image: landsoft/reporting-api
    network_mode: host
    build:
      context: ./app
    command: >
      sh -c "python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"
    volumes:
      - ./app:/code
    ports:
      - "8000:8000"
    environment:
      - DB_HOST="DESKTOP-RC52TD0\SQL2022"
      - DB_NAME=reporting
      - DB_USER=sa
      - DB_PASSWORD=Root_1421
      - DB_PORT=1433
    # depends_on:
    #   - sqlserver
    
# volumes:
#   sqlserver-data:
#     driver: local

Solution

  • Finally got it working.

    In the DATABASES configuration, i changed the HOST to use the ip address and port instead of the instance name. I also left the `PORT' blank.

    DATABASES = {
        'default': {
            'ENGINE': 'mssql',
            'NAME': 'reporting',
            'HOST': '192.168.211.225,56985', # use ip with port separated by comma
            'PORT': '', # left blank
            'USER': '...username..',
            'PASSWORD': '..password..',
            'OPTIONS': {
                'driver': 'ODBC Driver 17 for SQL Server',
            },
        }
    }
    

    This is my dockerfile:

    FROM ubuntu:18.04
    ENV PYTHONUNBUFFERED 1
    ENV DEBIAN_FRONTEND noninteractive
    
    RUN apt-get update && apt-get install -y curl apt-transport-https python3 python3-pip python3-venv python-dev locales nano
    RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
    RUN curl https://packages.microsoft.com/config/ubuntu/18.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
    RUN apt-get update && apt-get install -y gnupg2
    
    # ODBC 17 DEPENDENCIES
    ENV ACCEPT_EULA=Y
    RUN apt-get update && apt-get -y install msodbcsql17 freetds-dev tdsodbc
    
    RUN apt-get update && apt-get install mssql-tools
    # Add the necessary commands for setting up the environment
    RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
    RUN /bin/bash -c "source ~/.bashrc"
    
    RUN apt-get install -y unixodbc-dev
    
    RUN mkdir /code
    WORKDIR /code
    ADD requirements.txt /code/
    
    
    RUN python3 -m venv /venv
    ENV PATH="/venv/bin:$PATH"
    RUN /venv/bin/python -m pip install --upgrade pip && \
        /venv/bin/pip install -r requirements.txt -v
    
    ADD . /code/
    
    RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
    RUN locale-gen
    

    This is my requirements.txt file..

    Django==3.2.23
    mssql-django==1.3
    djangorestframework>=3.12.4,<=3.13
    drf-spectacular>=0.15.1,<=0.16
    Pillow>=8.2.0,<=8.3.0
    django-environ>=0.11.2,<=0.12
    

    Hopefully it helps someone facing similar problem..