Connect with Django
On this page
Note
This is a Preview feature.
Use the django-singlestore
connector to integrate your SingleStore database with a Django application.
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. |
Python |
3. |
To connect to SingleStore from your Django application,
-
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_
constraint) in columnstore tables, and the unique key must contain all the columns of the shard key.
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 supportedSHARD 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_
environment variables to any of the following values:SINGLESTORE_ TABLE_ STORAGE_ TYPE_ <APP_ NAME> "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 ModelStorageManagerclass 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_
environment variable(s) to disable enforcement of unique keys (UNIQUE
constraint) during migrations.
For example:
DJANGO_
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.
# Intermediary modelclass 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 queryCREATE 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.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.
Rollback Migrations
Most DDL statements in SingleStore trigger implicit commits.
Additional Remarks
-
The
OneToOneField
in a Django model must haveprimary_
.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 theserialize()
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
forSELECT * 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_
column in a columnstore table.INCREMENT -
Reset the value of the
AUTO_
column.INCREMENT -
Modify column type from
NULL
toNOT NULL
on a columnstore table.
-
-
FLOAT
orDOUBLE
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 supportedUNIQUE (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 asutf8mb4_
.general_ ci -
The
dumpdata
Django command does not support a table or a referenced many-to-many table that does not have anid
column.Refer to Custom DDL for many-to-many Relationships for more information. -
Refer to
django_
in features.test_ skips py for other unsupported use cases.
Example
The following example shows how to run the Django Polls tutorial using SingleStore.
-
Create a new Django project named djangoExample and change to the djangoExample directory.
django-admin startproject djangoExamplecd djangoExampleThis command creates the following directory structure and files:
djangoExample/ ├── manage.py └── djangoExample/ ├── __init__.py ├── settings.py ├── urls.py ├── asgi.py └── wsgi.py
-
Create a new Django app named polls.
python manage.py startapp pollsThis 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/*
-
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", ]
-
-
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" -
Create models.
Add the following to polls/models. py: # polls/models.pyfrom django.db import modelsfrom django_singlestore.schema import ModelStorageManagerclass Question(models.Model):question_text = models.CharField(max_length=200, unique=True)pub_date = models.DateTimeField("date published")# Store as REFERENCE to allow UNIQUE constraintobjects = ModelStorageManager(table_storage_type="REFERENCE")def __str__(self):return self.question_textclass 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 -
Generate migration files and then apply the migrations.
python manage.py makemigrationsMigrations for 'polls': polls/migrations/0001_initial.py + Create model Question + Create model Choice
python manage.py migrateOperations 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
-
Add the following code to polls/views.
py: from django.http import HttpResponsedef index(request):return HttpResponse("Hello, world. You're at the polls index.") -
Add the following code to polls/urls.
py: from django.urls import pathfrom . import viewsurlpatterns = [path("", views.index, name="index"),] -
Update djangoExample/urls.
py as follows: from django.contrib import adminfrom django.urls import include, pathurlpatterns = [path("polls/", include("polls.urls")),path("admin/", admin.site.urls),] -
Start the server.
python manage.py runserver -
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