百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
D

django-clickhouse-backend

> 后端框架
开源

Django 点击数据库后端。

198 stars0 点赞0 次浏览
访问官网GitHub

工具介绍

Django 点击数据库后端。

Django ClickHouse Database Backend

Django clickhouse backend is a django database backend for clickhouse database. This project allows using django ORM to interact with clickhouse, the goal of the project is to operate clickhouse like operating mysql, postgresql in django.

Thanks to clickhouse driver, django clickhouse backend use it as DBAPI. Thanks to clickhouse pool, it makes clickhouse connection pool.

Read Documentation for more.

Features:

  • Reuse most of the existed django ORM facilities, minimize your learning costs.
  • Connect to clickhouse efficiently via clickhouse native interface and connection pool.
  • No other intermediate storage, no need to synchronize data, just interact directly with clickhouse.
  • Support clickhouse specific schema features such as Engine and Index.
  • Support most types of table migrations.
  • Support creating test database and table, working with django TestCase and pytest-django.
  • Support most clickhouse data types.
  • Support SETTINGS in SELECT Query.
  • Support PREWHERE clause.
  • Support SAMPLE clause.
  • Support query results returned in columns and deserialized to numpy objects.

Notes:

  • Not tested upon all versions of clickhouse-server, clickhouse-server 22.x.y.z or over is suggested.
  • Aggregation functions result in 0 or nan (Not NULL) when data set is empty. max/min/sum/count is 0, avg/STDDEV_POP/VAR_POP is nan.
  • In outer join, clickhouse will set missing columns to empty values (0 for number, empty string for text, unix epoch for date/datatime) instead of NULL. So Count("book") resolve to 1 in a missing LEFT OUTER JOIN match, not 0. In aggregation expression Avg("book__rating", default=2.5), default=2.5 have no effect in a missing match.
  • Clickhouse does not support unique constraint and foreignkey constraint. ForeignKey, ManyToManyField and OneToOneField can be used with clickhouse backend, but no database level constraints will be added, so there could be some consistency problems.
  • Clickhouse does not support transaction. If any exception occurs during migrating, then your clickhouse database will be in an untracked state. Any migration should be full tested in test environment before deployed to production environment.
  • This project does not support migrations of changing table engine and settings yet.

Requirements:

  • Python >= 3.7
  • Django >= 3.2
  • clickhouse driver
  • clickhouse pool

Get started

Installation

$ pip install django-clickhouse-backend

or

$ git clone https://github.com/jayvynl/django-clickhouse-backend
$ cd django-clickhouse-backend
$ python setup.py install

Configuration

Only ENGINE is required in database setting, other options have default values.

  • ENGINE: required, set to clickhouse_backend.backend.
  • NAME: database name, default default.
  • HOST: database host, default localhost.
  • PORT: database port, default 9000.
  • USER: database user, default default.
  • PASSWORD: database password, default empty.

In the most cases, you may just use clickhouse to store some big events tables, and use some RDBMS to store other tables. Here I give an example setting for clickhouse and postgresql.

INSTALLED_APPS = [
    # ...
    "clickhouse_backend",
    # ...
]
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "HOST": "localhost",
        "USER": "postgres",
        "PASSWORD": "123456",
        "NAME": "postgres",
    },
    "clickhouse": {
        "ENGINE": "clickhouse_backend.backend",
        "NAME": "default",
        "HOST": "localhost",
        "USER": "DB_USER",
        "PASSWORD": "DB_PASSWORD",
    }
}
DATABASE_ROUTERS = ["dbrouters.ClickHouseRouter"]
# dbrouters.py
from clickhouse_backend.models import ClickhouseModel

def get_subclasses(class_):
    classes = class_.__subclasses__()

    index = 0
    while index  show create table django_migrations;

CREATE TABLE other.django_migrations
(
    `id` Int64,
    `app` FixedString(255),
    `name` FixedString(255),
    `applied` DateTime64(6, 'UTC')
)
ENGINE = MergeTree
ORDER BY id
SETTINGS index_granularity = 8192 

we can query it with results like this

> select * from django_migrations;

┌──────────────────id─┬─app─────┬─name─────────┬────────────────────applied─┐
│ 1626937818115211264 │ testapp │ 0001_initial │ 2023-02-18 13:32:57.538472 │
└─────────────────────┴─────────┴──────────────┴────────────────────────────┘

migrate will create a table with name event as we define in the models

…

Operate Data

create

for i in range(10):
    Event.objects.create(ip_nullable=None, port=i,
                         protocol="HTTP", content="test",
                         action=Event.Action.PASS.value)
assert Event.objects.count() == 10

query

queryset = Event.objects.filter(content="test")
for i in queryset:
    print(i)

update

Event.objects.filter(port__in=[1, 2, 3]).update(protocol="TCP")
time.sleep(1)
assert Event.objects.filter(protocol="TCP").count() == 3

delete

Event.objects.filter(protocol="TCP").delete()
time.sleep(1)
assert not Event.objects.filter(protocol="TCP").exists()

Except for the model definition, all other operations are like operating relational databases such as mysql and postgresql

Testing

Writing testcase is all the same as normal django project. You can use django TestCase or pytest-django. Notice: clickhouse use mutations for deleting or updating. By default, data mutations is processed asynchronously. That is, when you update or delete a row, clickhouse will perform the action after a period of time. So you should change this default behavior in testing for deleting or updating. There are 2 ways to do that:

  • Config database engine as follows, this sets mutations_sync=1 at session scope.
    DATABASES = {
        "default": {
            "ENGINE": "clickhouse_backend.backend",
            "OPTIONS": {
                "settings": {
                    "mutations_sync": 1,
                }
            }
        }
    }
    
  • Use SETTINGS in SELECT Query.
    Event.objects.filter(protocol="UDP").settings(mutations_sync=1).delete()
    

Sample test case.

from django.test import TestCase

class TestEvent(TestCase):
    databases = {"default", "clickhouse"}

    def test_spam(self):
        assert Event.objects.count() == 0

Distributed table

This backend support distributed DDL queries (ON CLUSTER clause) and distributed table engine.

The following example assumes that a cluster defined by docker compose in this repository is used. This cluster name is cluster, it has 2 shards, every shard has 2 replica.

Query results returned as columns and/or deserialized into numpy objects

clickhouse-driver allows results to be returned as columns and/or deserialized into numpy objects. This backend supports both options by using the context manager, Cursor.set_query_execution_args().

…

Configuration

…

Extra settings explanation:

  • "migration_cluster": "cluster" Migration table will be created on this cluster if this setting is specified, otherwise only local migration table is created.

  • "mutations_sync": 2 This is suggested if you want to test data mutations on replicated table. Don't set this in production environment.

  • "insert_distributed_sync": 1 This is suggested if you want to test inserting data into distributed table. Don't set this in production environment.

  • "insert_quorum": 2 This is suggested if you want to test inserting data into replicated table. The value is set to replica number.

  • "alter_sync": 2 This is suggested if you want to test altering or truncating replicated table. Don't set this in production environment.

  • "TEST": {"cluster": "cluster", "managed": False, "DEPENDENCIES": ["default"]} Test database will be created on this cluster. If you have multiple database connections to the same cluster and want to run tests over all these connections, then only one connection should set "managed": True(the default value), other connections should set "managed": False. So that test database will not be created multiple times.

    If your managed database alias is s1r2 instead default, "DEPENDENCIES": ["s1r2"] should be set to ensure the creation order for test databases.

    Do not hardcode database name when you define replicated table or distributed table. Because test database name is different from deployed database name.

Clickhouse cluster behind a load balancer

If your clickhouse cluster is running behind a load balancer, you can optionally set distributed_migrations to True under database OPTIONS. Then a distributed migration table will be created on all nodes of the cluster, and all migration operations will be performed on this distributed migrations table instead of a local migrations table. Otherwise, sequentially running migrations will have no effect on other nodes.

Configuration example:

DATABASES = {
    "default": {
        "HOST": "clickhouse-load-balancer",
        "PORT": 9000,
        "ENGINE": "clickhouse_backend.backend",
        "OPTIONS": {
            "migration_cluster": "cluster",
            "distributed_migrations": True,
            "settings": {
                "mutations_sync": 2,
                "insert_distributed_sync": 1,
                "insert_quorum": 2,
                "alter_sync": 2,
            },
        },
    }
}

Model

cluster in Meta class will make models being created on cluster.

…

CRUD

Just like normal table, you can do whatever you like to distributed table.

students = DistributedStudent.objects.bulk_create([DistributedStudent(name=f"Student{i}", score=i * 10) for i in range(10)])
assert DistributedStudent.objects.count() == 10
DistributedStudent.objects.filter(id__in=[s.id for s in students[5:]]).update(name="lol")
DistributedStudent.objects.filter(id__in=[s.id for s in students[:5]]).delete()

Migrate

If migration_cluster is not specified in database configuration. You should always run migrating on one specific cluster node. Because other nodes do not know whether migrations have been applied by any other node.

If migration_cluster is

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

Pythonclickhousedatabasedjangoorm

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月18日
分类后端框架
定价开源

> 相关工具

N
Node.js
基于 V8 的 JavaScript 运行时
D
Django
Python 高级 Web 框架
S
Spring Boot
Java 生态主流微服务框架