# Connect with Django

> **📝 Note**: This is a Preview feature.

Use the `django-singlestore` connector to integrate your SingleStore database with a Django application. The connector enables you to power your Django-based, data-intensive web applications with SingleStore across multiple use cases, including real-time dashboards and analytics, IoT, SaaS platforms, and more.

Refer to the [SingleStore backend for Django](https://github.com/singlestore-labs/django-singlestore) GitHub repository for the connector's source code and related information.

The following matrix shows the versions of Django and Python that the `django-singlestore` connector supports:

| Django | 4.2  |
| ------ | ---- |
| Python | 3.9+ |

To connect to SingleStore from your Django application,

1. [Install the django-singlestore connector](https://docs.singlestore.com/#section-id235153653397817.md).

2. [Configure the DATABASES setting](https://docs.singlestore.com/#section-id235153653927948.md) in your application configuration.

## Install the `django-singlestore` Connector

Run the following command to install the `django-singlestore` connector from PyPI:

```shell
pip install django-singlestore
```

To install the connector from source (GitHub repository) instead, run the following command:

```shell
pip install git+https://github.com/singlestore-labs/django-singlestore
```

## Configure the `DATABASES` Setting

Add (or update) the `DATABASES` and other related settings in the Django application configuration as follows:

```
DATABASES = {
    "default": {
        "ENGINE": "django_singlestore",
        "HOST": "<endpoint>",
        "PORT": 3306,
        "USER": "<username>",
        "PASSWORD": "<password>",
        "NAME": "<database>",
    },
}

# SingleStore does not support datetime with timezones
USE_TZ = False

# AUTO_INCREMENT columns must have BIGINT data type
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
```

where,

* `endpoint`: IP address or hostname of the SingleStore deployment.
* `port`: Port of the SingleStore deployment.
* `username`: Username of the SingleStore database user.
* `password`: Password for the SingleStore database user.
* `database`: Name of the SingleStore database to connect with.

## Remarks

## Handle Unique Key Constraints

SingleStore only supports a single unique key (`UNIQUE(column_list)` constraint) in columnstore tables, and the unique key must contain all the columns of the shard key. (Refer to [Sharding](https://docs.singlestore.com/db/v9.1/introduction/distributed-architecture/sharding.md) and [Creating a Columnstore Table](https://docs.singlestore.com/db/v9.1/create-a-database/creating-a-columnstore-table.md) for more information.) This limitation does not apply to [reference tables](https://docs.singlestore.com/db/v9.1/create-a-database/other-schema-concepts/#UUID-712159bb-3006-3563-f42d-6188153d809f.md).

For example, the following table definition is not supported because the `UNIQUE` key does not contain the `SHARD key` column:

```sql
CREATE TABLE user_group (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT,
  group_id BIGINT,
  UNIQUE (user_id, group_id), -- not supported
  SHARD KEY (id));
```

To address this unique key limitation, the `django-singlestore` connector provides the following mechanisms:

* [Use custom table storage type](https://docs.singlestore.com/#section-id235153658361497.md)
* [Disable enforcement of UNIQUE constraint](https://docs.singlestore.com/#section-id235153658676244.md)
* [Custom DDL for many-to-many relationships](https://docs.singlestore.com/#section-id235153658769599.md)

## Use Custom Table Storage Type

You can configure the table storage type using either of the following (in the respective scope):

* **Per application**: Set the `DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_<APP_NAME>` environment variables to any of the following values: `"ROWSTORE"`, `"REFERENCE"`, `"ROWSTORE REFERENCE"`. For example:
  ```shell
  export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_ADMIN="ROWSTORE REFERENCE"
  export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_AUTH="ROWSTORE REFERENCE"
  export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_CONTENTTYPES="ROWSTORE REFERENCE"
  export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_SITES="ROWSTORE REFERENCE"
  ```
* **Per model**: Specify the storage type for each model. For example:
  ```Python
  from django_singlestore.schema import ModelStorageManager

  class Food(models.Model):
      name = models.CharField(max_length=20, unique=True)

      objects = ModelStorageManager(table_storage_type="REFERENCE")

      def __str__(self):
          return self.name
  ```

## Disable Enforcement of `UNIQUE` Constraint

Configure the `DJANGO_SINGLESTORE_NOT_ENFORCED_UNIQUE_<APP_NAME>` environment variable(s) to disable enforcement of unique keys (`UNIQUE` constraint) during migrations.

For example:

`DJANGO_SINGLESTORE_NOT_ENFORCED_UNIQUE_<APP_NAME>=1`

> **📝 Note**: SingleStore does not recommend using this option in production environments because it masks the lack of unique constraint in the database from application developers.

## Custom DDL for Many-to-Many Relationships

For many-to-many relationships, define an intermediary model (`through`) and use a custom DDL query. For example:

```Python
# Intermediary model
class Paragraph(models.Model):
    text = models.TextField()
    page = models.ManyToManyField("Page", through="ParagraphPage")

class ParagraphPage(models.Model):
    paragraph = models.ForeignKey(Paragraph)
    page = models.ForeignKey("Page")

    class Meta:
        unique_together = (('paragraph', 'page'),)
        db_table = "queries_paragraph_page"
```

```sql
-- Custom DDL query
CREATE TABLE `queries_paragraph_page` (
  `paragraph_id` BIGINT NOT NULL,
  `page_id` BIGINT NOT NULL,
  SHARD KEY (`paragraph_id`),
  UNIQUE KEY (`paragraph_id`, `page_id`),
  KEY (`paragraph_id`),
  KEY (`page_id`)
);

```

> **📝 Note**: Because the `through` model does not have a primary key column, some Django features may not function as expected. Also, the `serialize()` method may behave differently because the serialized output does not contain the `id`/primary key field.

## Write to Reference Tables

For reference tables, DML queries in multi-statement transactions are only supported on the Master Aggregator node. Refer to [DML Forwarding for Reference Tables](https://docs.singlestore.com/db/v9.1/create-a-database/other-schema-concepts/#section-idm4629858971148832533810452488.md) for more information.

## Rollback Migrations

Most DDL statements in SingleStore trigger implicit commits. Therefore, if a migration is only partially applied, some changes may commit and require manual rollback.

## Additional Remarks

* The `OneToOneField` in a Django model must have `primary_key=True`. Otherwise, it must be materialized as a reference table.
* If the definition of the many-to-many field is modified to include the `through` (custom) model, the result of the `serialize()` method for this model changes as well. The serialized output will not include the related field values because Django ignores custom models during serialization.
  ```python
  def handle_m2m_field(self, obj, field):
      if field.remote_field.through._meta.auto_created:
  ```
* There is no implicit `ORDER BY id` for `SELECT * FROM <table>` queries.

## Limitations

SingleStore does not support the following:

* Foreign keys: The Django application must handle the foreign keys to ensure referential integrity.
* `ALTER TABLE` commands that perform the following:

  * Modify the data type of a column in a columnstore table: Instead, you must create a new column, copy data to the new column, drop the original column, and then rename the new column.
  * Add a unique/primary/foreign key (or index).
  * Change the primary key column in a columnstore table.
  * Modify the table comment.
  * Drop a shard key on a sharded columnstore table.
  * Add or drop the `AUTO_INCREMENT` column in a columnstore table.
  * Reset the value of the `AUTO_INCREMENT` column.
  * Modify column type from `NULL` to `NOT NULL` on a columnstore table.
* `FLOAT` or `DOUBLE` data type for primary keys in columnstore tables.
* Reference tables without a primary key.
* Multiple `UNIQUE` indexes where at least one index contains multiple columns on a columnstore table. For example:
  ```sql
  -- not supported
  UNIQUE (user_id, session_id),  
  UNIQUE (event_id)
  ```
* Multiple hash indexes on the same column.
* Nested transactions.
* Fetching an instance of a custom `through` model using `.objects.get()`.
* Case-insensitive filters require casting the filtered column to a `TextField` with a case-insensitive collation, such as `utf8mb4_general_ci`.
* The `dumpdata` Django command does not support a table or a referenced many-to-many table that does not have an `id` column. Refer to [Custom DDL for many-to-many Relationships](https://docs.singlestore.com/#section-id235153658769599.md) for more information.
* Refer to `django_test_skips` in [features.py](https://github.com/singlestore-labs/django-singlestore/blob/main/django_singlestore/features.py) for other unsupported use cases.

## Example

The following example shows how to run the Django Polls tutorial using SingleStore.

1. Create a new Django project named **djangoExample** and change to the **djangoExample** directory.
   ```shell
   django-admin startproject djangoExample
   cd djangoExample
   ```
   This command creates the following directory structure and files:
   ```
   djangoExample/
   ├── manage.py
   └── djangoExample/
       ├── __init__.py
       ├── settings.py
       ├── urls.py
       ├── asgi.py
       └── wsgi.py
   ```

2. Create a new Django app named **polls**.
   ```python
   python manage.py startapp polls
   ```
   This command creates the following directory structure and files:
   ```
   djangoExample/
   ├── polls/
       ├── __init__.py
       ├── admin.py
       ├── apps.py
       ├── migrations/
       │   └── __init__.py
       ├── models.py
       ├── tests.py
       └── views.py
   ├── djangoExample/*
   ```

3. Update the following in **djangoExample/settings.py**.

   * Database setting:
     ```
     DATABASES = {
         "default": {
             "ENGINE": "django_singlestore",
             "HOST": "<endpoint>",
             "PORT": 3306,
             "USER": "<username>",
             "PASSWORD": "<password>",
             "NAME": "<databas>",
         },
     }
     ```
   * Disable timezone:
     ```
     USE_TZ = False
     ```
   * Add the **polls** app to installed apps:
     ```
     INSTALLED_APPS = [
         ...
         "polls",
     ]
     ```

4. Configure the following environment variables to change the default table type for compatibility:
   ```shell
   export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_AUTH="ROWSTORE REFERENCE"
   export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_ADMIN="ROWSTORE REFERENCE"
   export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_CONTENTTYPES="ROWSTORE REFERENCE"
   export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_SITES="ROWSTORE REFERENCE"
   ```

5. Create models. Add the following to **polls/models.py**:
   ```python
   # polls/models.py

   from django.db import models
   from django_singlestore.schema import ModelStorageManager

   class Question(models.Model):
       question_text = models.CharField(max_length=200, unique=True)
       pub_date = models.DateTimeField("date published")

       # Store as REFERENCE to allow UNIQUE constraint
       objects = ModelStorageManager(table_storage_type="REFERENCE")

       def __str__(self):
           return self.question_text


   class Choice(models.Model):
       question = models.ForeignKey(Question, on_delete=models.CASCADE)
       choice_text = models.CharField(max_length=200)
       votes = models.IntegerField(default=0)

       def __str__(self):
           return self.choice_text
   ```

6. Generate migration files and then apply the migrations.
   ```shell
   python manage.py makemigrations

   ```
   ```output

   Migrations for 'polls':
     polls/migrations/0001_initial.py
       + Create model Question
       + Create model Choice
   ```
   ```shell
   python manage.py migrate

   ```
   ```output

   Operations to perform:
     Apply all migrations: admin, auth, contenttypes, polls, sessions
   Running migrations:
     Applying contenttypes.0001_initial... OK
     Applying auth.0001_initial... OK
     Applying admin.0001_initial... OK
     Applying admin.0002_logentry_remove_auto_add... OK
     Applying admin.0003_logentry_add_action_flag_choices... OK
     Applying contenttypes.0002_remove_content_type_name... OK
     Applying auth.0002_alter_permission_name_max_length... OK
     Applying auth.0003_alter_user_email_max_length... OK
     Applying auth.0004_alter_user_username_opts... OK
     Applying auth.0005_alter_user_last_login_null... OK
     Applying auth.0006_require_contenttypes_0002... OK
     Applying auth.0007_alter_validators_add_error_messages... OK
     Applying auth.0008_alter_user_username_max_length... OK
     Applying auth.0009_alter_user_last_name_max_length... OK
     Applying auth.0010_alter_group_name_max_length... OK
     Applying auth.0011_update_proxy_permissions... OK
     Applying auth.0012_alter_user_first_name_max_length... OK
     Applying polls.0001_initial... OK
     Applying sessions.0001_initial... OK
   ```

7. Add the following code to **polls/views.py**:
   ```python
   from django.http import HttpResponse

   def index(request):
       return HttpResponse("Hello, world. You're at the polls index.")
   ```

8. Add the following code to **polls/urls.py**:
   ```python
   from django.urls import path
   from . import views

   urlpatterns = [
       path("", views.index, name="index"),
   ]
   ```

9. Update **djangoExample/urls.py** as follows:
   ```python
   from django.contrib import admin
   from django.urls import include, path

   urlpatterns = [
       path("polls/", include("polls.urls")),
       path("admin/", admin.site.urls),
   ]
   ```

10. Start the server.
    ```shell
    python manage.py runserver
    ```

11. Go to <http://localhost:8000/polls/>. Upon a successful server start, the following message is displayed in the browser:

    `Hello, world. You're at the polls index.`

Refer to [Writing your first Django app, part 1](https://docs.djangoproject.com/en/dev/intro/tutorial01/) for related information.

***

Modified at: September 29, 2025

Source: [/db/v9.1/developer-resources/connect-with-application-development-tools/connect-with-python/connect-with-django/](https://docs.singlestore.com/db/v9.1/developer-resources/connect-with-application-development-tools/connect-with-python/connect-with-django/)

(An index of the documentation is available at /llms.txt)
