Important

The SingleStore 9.0 release candidate (RC) gives you the opportunity to preview, evaluate, and provide feedback on new and upcoming features prior to their general availability. In the interim, SingleStore 8.9 is recommended for production workloads, which can later be upgraded to SingleStore 9.0.

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 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.

  2. Configure the DATABASES setting in your application configuration.

Install the django-singlestore Connector

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

pip install django-singlestore

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

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.

  • 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 and Creating a Columnstore Table for more information.) This limitation does not apply to reference tables.

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

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

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:

    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:

    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:

# 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"
-- 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 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.

    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:

    -- 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 for more information.

  • Refer to django_test_skips in 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.

    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 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:

    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:

    # 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.

    python manage.py makemigrations
    Migrations for 'polls':
      polls/migrations/0001_initial.py
        + Create model Question
        + Create model Choice
    python manage.py migrate
    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:

    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:

    from django.urls import path
    from . import views
    urlpatterns = [
    path("", views.index, name="index"),
    ]
  9. Update djangoExample/urls.py as follows:

    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.

    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 for related information.

Last modified: September 15, 2025

Was this article helpful?

Verification instructions

Note: You must install cosign to verify the authenticity of the SingleStore file.

Use the following steps to verify the authenticity of singlestoredb-server, singlestoredb-toolbox, singlestoredb-studio, and singlestore-client SingleStore files that have been downloaded.

You may perform the following steps on any computer that can run cosign, such as the main deployment host of the cluster.

  1. (Optional) Run the following command to view the associated signature files.

    curl undefined
  2. Download the signature file from the SingleStore release server.

    • Option 1: Click the Download Signature button next to the SingleStore file.

    • Option 2: Copy and paste the following URL into the address bar of your browser and save the signature file.

    • Option 3: Run the following command to download the signature file.

      curl -O undefined
  3. After the signature file has been downloaded, run the following command to verify the authenticity of the SingleStore file.

    echo -n undefined |
    cosign verify-blob --certificate-oidc-issuer https://oidc.eks.us-east-1.amazonaws.com/id/CCDCDBA1379A5596AB5B2E46DCA385BC \
    --certificate-identity https://kubernetes.io/namespaces/freya-production/serviceaccounts/job-worker \
    --bundle undefined \
    --new-bundle-format -
    Verified OK