You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多数据库环境创建用户时默认数据库配置报错问题

Django多数据库配置下创建用户报错的解决办法

问题场景

我有一个配置了多数据库的Django项目,数据库配置如下:

DATABASES = {
    'default': {},
    'db1': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB1_NAME,
    },
    'db2': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB2_NAME,            
    }
}

DATABASE_ROUTERS = ['app.router1.Router1', 'app.router2.Router2']

db1对应的路由Router1定义:

class Router1:
    route_app_labels = {'app', 'sessions', 'auth', 'admin', 'contenttypes'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'db1'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'db1'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == 'db1'
        return None

项目除创建新用户外其他功能正常,创建用户时抛出错误:

django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

将db1改为default后,用户创建功能恢复正常,完整错误栈如下:

Traceback (most recent call last):
  File "/.venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/.venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/.venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/.venv/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/.venv/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/.venv/lib/python3.9/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
  File "/.venv/lib/python3.9/site-packages/djoser/views.py", line 136, in perform_create
    user = serializer.save()
  File "/.venv/lib/python3.9/site-packages/rest_framework/serializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "/.venv/lib/python3.9/site-packages/djoser/serializers.py", line 65, in create
    user = self.perform_create(validated_data)
  File "/.venv/lib/python3.9/site-packages/djoser/serializers.py", line 72, in perform_create
    with transaction.atomic():
  File "/.venv/lib/python3.9/site-packages/django/db/transaction.py", line 197, in __enter__
    if not connection.get_autocommit():
  File "/.venv/lib/python3.9/site-packages/django/db/backends/base/base.py", line 455, in get_autocommit
    self.ensure_connection()
  File "/.venv/lib/python3.9/site-packages/django/db/backends/dummy/base.py", line 20, in complain
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

问题原因

从错误栈可以看出,问题出在transaction.atomic()调用上。Django的transaction.atomic()默认会使用default数据库,但当前配置里default是空字典,未指定ENGINE参数,因此触发配置错误。

尽管路由Router1已经将auth(用户模型所属的app)指向db1,但transaction.atomic()在未指定数据库的情况下,仍会尝试使用default数据库连接,而该连接是未配置的dummy后端,最终导致报错。

解决方案

方案1:给default数据库配置实际连接(推荐)

直接将default指向已配置的db1,让默认事务使用正确的数据库:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB1_NAME,
    },
    'db1': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB1_NAME,
    },
    'db2': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB2_NAME,            
    }
}

也可以通过复用配置避免重复代码:

DB1_CONFIG = {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': BASE_DIR / DB1_NAME,
}

DATABASES = {
    'default': DB1_CONFIG,
    'db1': DB1_CONFIG,
    'db2': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / DB2_NAME,            
    }
}

方案2:修改事务代码,指定使用db1

如果不想修改default配置,可以自定义Djoser的序列化器,在perform_create中指定事务使用的数据库:

from djoser.serializers import UserCreateSerializer
from django.db import transaction

class CustomUserCreateSerializer(UserCreateSerializer):
    def perform_create(self, validated_data):
        # 指定使用db1的事务
        with transaction.atomic(using='db1'):
            return super().perform_create(validated_data)

然后在Djoser配置中替换默认序列化器:

# settings.py
DJOSER = {
    'SERIALIZERS': {
        'user_create': 'your_app.serializers.CustomUserCreateSerializer',
    },
}

方案3:完善数据库路由的事务处理

可以通过修改路由逻辑,让Django处理auth模型事务时自动选择db1,但该方案逻辑相对复杂,不如前两种直观,因此不优先推荐。

内容的提问来源于stack exchange,提问作者michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:45:38