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. -
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_ 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
OneToOneFieldin 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 idforSELECT * 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 TABLEcommands 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
NULLtoNOT NULLon a columnstore table.
-
-
FLOATorDOUBLEdata type for primary keys in columnstore tables. -
Reference tables without a primary key.
-
Multiple
UNIQUEindexes 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
throughmodel using..objects. get() -
Case-insensitive filters require casting the filtered column to a
TextFieldwith a case-insensitive collation, such asutf8mb4_.general_ ci -
The
dumpdataDjango command does not support a table or a referenced many-to-many table that does not have anidcolumn.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 Choicepython 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 29, 2025