如何在空 'default' 的 Django 中使用多个数据库?

How to use multiple databases in Django with an empty 'default'?

我正在尝试在 Django 中创建一个多数据库项目。但是我在将我的模型正确迁移到适当的数据库时遇到了问题。

我使用 'Writing your first Django app' 教程作为起点;所以...我写了以下数据库路由器;这个用于 'polls' 应用程序:

class PollsRouter:

route_app_labels = {'polls'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'polls' or
        obj2._meta.app_label == 'polls'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'polls':
        return db == 'Polls'
    return None

还有 'devices' 应用程序的路由器 class:

class DevicesRouter:

route_app_labels = {'devices'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'devices' or
        obj2._meta.app_label == 'devices'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'devices':
        return db == 'CTS_ER_BD'
    return None

最后,'auth_user' 数据库的路由器 class(对于本机 Django 应用程序)

class Auth_userRouter:

    route_app_labels = {'auth', 'contenttypes', 'admin', 'sessions'}

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

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        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 == 'Auth_user_db'
        return None

当然...我已经将我的应用程序和路由器包含在 settings.py 中,如下所示:

DATABASES = {
    'default': {},
    'Auth_user_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'auth_db',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'CTS_ER_BD': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'CTS_ER_BD',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'Polls': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'polls',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    }

}

DATABASE_ROUTERS = [
        'routers.Polls_router.PollsRouter',
        'routers.Devices_router.DevicesRouter',
        'routers.Auth_user_router.Auth_userRouter'
    ]

当我尝试执行迁移时出现问题,这是我在创建迁移文件之前的项目树:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    └── Polls_router.py

4 directories, 23 files

显然迁移已正确创建为:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations devices
Migrations for 'devices':
  devices/migrations/0001_initial.py
    - Create model AuthUsers
    - Create model Devices
    - Create model DeviceTypes
    - Create model FirmwareVers
    - Create model HardwareVers
    - Create model Historicals
    - Create model Metadata
    - Create model Projects
    - Create model SoftwareVers
    - Create model Tests
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── settings.cpython-39.pyc
│   │   └── urls.cpython-39.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-39.pyc
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    ├── Polls_router.py
    └── __pycache__
        ├── Auth_user_router.cpython-39.pyc
        ├── Devices_router.cpython-39.pyc
        └── Polls_router.cpython-39.pyc

12 directories, 48 files

问题是,当我检查 devices 应用程序的 sqlmigrate 输出时,我看不到正确的 SQL 脚本:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate devices 0001 --database=CTS_ER_BD
--
-- Create model AuthUsers
--
--
-- Create model Devices
--
--
-- Create model DeviceTypes
--
--
-- Create model FirmwareVers
--
--
-- Create model HardwareVers
--
--
-- Create model Historicals
--
--
-- Create model Metadata
--
--
-- Create model Projects
--
--
-- Create model SoftwareVers
--
--
-- Create model Tests
--
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ 

这导致当我 运行 python3 manage.py migrate devices --database=CTS_ER_BD for devices:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py migrate devices --database=CTS_ER_BD
Operations to perform:
  Apply all migrations: devices
Running migrations:
  Applying devices.0001_initial... OK

伙计们,我正在尝试在 Django 中创建一个多数据库项目。但是我在将我的模型正确迁移到适当的数据库时遇到了问题。

我使用 'Writing your first Django app' 教程作为起点;所以...我写了以下数据库路由器;这个用于 'polls' 应用程序:

class PollsRouter:

route_app_labels = {'polls'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'polls' or
        obj2._meta.app_label == 'polls'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'polls':
        return db == 'Polls'
    return None

还有 'devices' 应用程序的路由器 class:

class DevicesRouter:

route_app_labels = {'devices'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'devices' or
        obj2._meta.app_label == 'devices'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'devices':
        return db == 'CTS_ER_BD'
    return None

最后,'auth_user' 数据库的路由器 class(对于本机 Django 应用程序)

class Auth_userRouter:

    route_app_labels = {'auth', 'contenttypes', 'admin', 'sessions'}

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

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        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 == 'Auth_user_db'
        return None

当然...我已经将我的应用程序和路由器包含在 settings.py 中,如下所示:

DATABASES = {
    'default': {},
    'Auth_user_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'auth_db',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'CTS_ER_BD': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'CTS_ER_BD',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'Polls': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'polls',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    }

}

DATABASE_ROUTERS = [
        'routers.Polls_router.PollsRouter',
        'routers.Devices_router.DevicesRouter',
        'routers.Auth_user_router.Auth_userRouter'
    ]

当我尝试执行迁移时出现问题,这是我在创建迁移文件之前的项目树:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    └── Polls_router.py

4 directories, 23 files

显然迁移已正确创建为:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations devices
Migrations for 'devices':
  devices/migrations/0001_initial.py
    - Create model AuthUsers
    - Create model Devices
    - Create model DeviceTypes
    - Create model FirmwareVers
    - Create model HardwareVers
    - Create model Historicals
    - Create model Metadata
    - Create model Projects
    - Create model SoftwareVers
    - Create model Tests
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── settings.cpython-39.pyc
│   │   └── urls.cpython-39.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-39.pyc
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    ├── Polls_router.py
    └── __pycache__
        ├── Auth_user_router.cpython-39.pyc
        ├── Devices_router.cpython-39.pyc
        └── Polls_router.cpython-39.pyc

12 directories, 48 files

问题是,当我检查 devices 应用程序的 sqlmigrate 输出时,我看不到正确的 SQL 脚本:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate devices 0001 --database=CTS_ER_BD
--
-- Create model AuthUsers
--
--
-- Create model Devices
--
--
-- Create model DeviceTypes
--
--
-- Create model FirmwareVers
--
--
-- Create model HardwareVers
--
--
-- Create model Historicals
--
--
-- Create model Metadata
--
--
-- Create model Projects
--
--
-- Create model SoftwareVers
--
--
-- Create model Tests
--
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ 

这导致当我 运行 python3 manage.py migrate devices --database=CTS_ER_BD for devices:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py migrate devices --database=CTS_ER_BD
Operations to perform:
  Apply all migrations: devices
Running migrations:
  Applying devices.0001_initial... OK

未创建相应数据库中的表:

MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations   |
+---------------------+

但显然 devices 应用程序的迁移已正确生成! (我没有粘贴它,以免 post 变长)

所以我不明白为什么 sqlmigrate 没有显示正确的 sql 脚本。或者没有正确执行迁移。

我不确定这是否可能是因为两个迁移文件实际上以相同的方式调用 (0001_initial.py),我是否应该为每个应用程序选择一个不同的文件?无论如何......两者都在不同的文件夹中,所以我没有看到任何问题。

民意调查和 Django 本机应用程序的迁移正常工作(显然),事实上,对于 'polls' 应用程序,您可以看到 sqlmigrate

的正确输出
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate polls 0001 --database=Polls
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `question_id` bigint NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$

所以我不确定我做错了什么。如果你想看这个项目......我在 GitLab https://gitlab.com/ralbarran1/multiple-db-in-django

中跟踪它

非常感谢,如果问题太长或重复,我很抱歉,我可以看到几个类似的问题,但我认为太旧了。

没有创建相应的数据库:

MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations   |
+---------------------+

但显然 devices 应用程序的迁移已正确生成!:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ cat devices/migrations/0001_initial.py 
# Generated by Django 4.0.4 on 2022-04-29 09:39

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='AuthUsers',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('user_name', models.CharField(max_length=50)),
            ],
            options={
                'db_table': 'auth_users',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Devices',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('serial_number', models.IntegerField()),
                ('manufacture_date', models.DateTimeField(blank=True, null=True)),
                ('devices_tag', models.ImageField(blank=True, null=True, upload_to='')),
            ],
            options={
                'db_table': 'devices',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='DeviceTypes',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('device_name', models.CharField(max_length=50)),
                ('client_ref', models.CharField(max_length=100)),
                ('colway_ref', models.CharField(max_length=100)),
                ('power_dis', models.IntegerField(blank=True, null=True)),
            ],
            options={
                'db_table': 'device_types',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='FirmwareVers',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('firmware_name', models.CharField(blank=True, max_length=50, null=True)),
                ('manuf_type', models.CharField(blank=True, max_length=50, null=True)),
            ],
            options={
                'db_table': 'firmware_vers',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='HardwareVers',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('hw_type', models.CharField(blank=True, db_column='HW_type', max_length=1, null=True)),
            ],
            options={
                'db_table': 'hardware_vers',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Historicals',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('test_date', models.DateTimeField(blank=True, null=True)),
                ('reuslt', models.BooleanField(blank=True, null=True)),
            ],
            options={
                'db_table': 'historicals',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Metadata',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ],
            options={
                'db_table': 'metadata',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Projects',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('project_name', models.CharField(blank=True, max_length=50, null=True)),
            ],
            options={
                'db_table': 'projects',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='SoftwareVers',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('colway_ref', models.CharField(blank=True, max_length=100, null=True)),
                ('joifi_ref', models.CharField(blank=True, max_length=100, null=True)),
            ],
            options={
                'db_table': 'software_vers',
                'managed': False,
            },
        ),
        migrations.CreateModel(
            name='Tests',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('test_name', models.CharField(blank=True, max_length=50, null=True)),
                ('prefix', models.CharField(blank=True, max_length=1, null=True)),
            ],
            options={
                'db_table': 'tests',
                'managed': False,
            },
        ),
    ]

所以我不明白为什么 sqlmigrate 没有显示正确的 sql 脚本。或者没有正确执行迁移。

我不确定这是否可能是因为两个迁移文件实际上以相同的方式调用 (0001_initial.py),我是否应该为每个应用程序选择一个不同的文件?无论如何......两者都在不同的文件夹中,所以我没有看到任何问题。

民意调查和 Django 本机应用程序的迁移正常工作(显然),事实上,对于 'polls' 应用程序,您可以看到 sqlmigrate

的正确输出
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate polls 0001 --database=Polls
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `question_id` bigint NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$

所以我不确定我做错了什么。如果你想看这个项目......我在 GitLab https://gitlab.com/ralbarran1/multiple-db-in-django

中跟踪它

非常感谢,如果问题太长或重复,我很抱歉,我可以看到几个类似的问题,但我认为太旧了。

问题实际上出在模型中:

class DeviceTypes(models.Model):
    device_name = models.CharField(max_length=50)
    client_ref = models.CharField(max_length=100)
    colway_ref = models.CharField(max_length=100)
    power_dis = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return f'{self.colway_ref}', {self.device_name}

    class Meta:
        managed = Fase
        db_table = 'device_types'

META OPTIONS managed = False 阻止 Django 管理此模型。

这是因为我让 Django 使用 python manage.py inspectdb > models.py 从 SQL 脚本生成模型,默认设置为 managed = False