如何删除多数据库中的django模型用户?

Guo*_*aqi 5 python django django-models

例如,我有一个包含两个应用程序(myapp、myapp2)的项目(mysite)。这些应用程序使用不同的数据库:

\n\n

设置.py:

\n\n
DATABASES = {\n    "default": {\n        "ENGINE": "django.db.backends.postgresql",\n        "HOST": "127.0.0.1",\n        "USER": "postgres",\n        "PASSWORD": "root",\n        "PORT": "5432",\n        "NAME": "test",\n    },\n    "test": {\n        "ENGINE": "django.db.backends.mysql",\n        "HOST": "127.0.0.1",\n        "USER": "root",\n        "PASSWORD": "root",\n        "PORT": "3306",\n        "NAME": "test",\n    },\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我编写一个数据库路由器:

\n\n
from django.conf import settings\n\n\nclass AppRouter:\n    def db_for_read(self, model, **hints):\n        return settings.APP_DB_MAPPER.get(model._meta.app_label)\n\n    def db_for_write(self, model, **hints):\n        return settings.APP_DB_MAPPER.get(model._meta.app_label)\n\n    def allow_relation(self, obj1, obj2, **hints):\n        db1 = settings.APP_DB_MAPPER.get(obj1._meta.app_label)\n        db2 = settings.APP_DB_MAPPER.get(obj2._meta.app_label)\n        if db1 and db2:\n            if db1 == db2:\n                return True\n            else:\n                return False\n        return None\n\n    def allow_migrate(self, db, app_label, model_name=None, **hints):\n        if app_label in settings.APP_DB_MAPPER:\n            return db == settings.APP_DB_MAPPER[app_label]\n        return None\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后应用它。

\n\n

设置.py:

\n\n
DATABASE_ROUTERS = ["mysite.app_router.AppRouter"]\n\nAPP_DB_MAPPER = {"myapp": "default", "myapp2": "test"}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在每个应用程序中添加一个模型:

\n\n

myapp/models.py:

\n\n
from django.db import models\nfrom django.contrib.auth.models import User\n\n\nclass TestDefault(models.Model):\n    name = models.CharField(max_length=100)\n    user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)\n
Run Code Online (Sandbox Code Playgroud)\n\n

myapp2/models.py:

\n\n
from django.db import models\nfrom django.contrib.auth.models import User\n\n\nclass TestApp(models.Model):\n    name = models.CharField(max_length=100)\n    user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)\n
Run Code Online (Sandbox Code Playgroud)\n\n

迁移后,将创建这些表:

\n\n

mysql(“测试”数据库):

\n\n
+----------------------------+\n| Tables_in_test             |\n+----------------------------+\n| auth_group                 |\n| auth_group_permissions     |\n| auth_permission            |\n| auth_user                  |\n| auth_user_groups           |\n| auth_user_user_permissions |\n| django_admin_log           |\n| django_content_type        |\n| django_migrations          |\n| django_session             |\n| myapp2_testapp             |\n+----------------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

postgres(“默认”数据库):

\n\n
+----------+----------------------------+--------+----------+\n| Schema   | Name                       | Type   | Owner    |\n|----------+----------------------------+--------+----------|\n| public   | auth_group                 | table  | postgres |\n| public   | auth_group_permissions     | table  | postgres |\n| public   | auth_permission            | table  | postgres |\n| public   | auth_user                  | table  | postgres |\n| public   | auth_user_groups           | table  | postgres |\n| public   | auth_user_user_permissions | table  | postgres |\n| public   | django_admin_log           | table  | postgres |\n| public   | django_content_type        | table  | postgres |\n| public   | django_migrations          | table  | postgres |\n| public   | django_session             | table  | postgres |\n| public   | myapp_testdefault          | table  | postgres |\n+----------+----------------------------+--------+----------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我尝试在 shell 中测试关系:

\n\n
+----------------------------+\n| Tables_in_test             |\n+----------------------------+\n| auth_group                 |\n| auth_group_permissions     |\n| auth_permission            |\n| auth_user                  |\n| auth_user_groups           |\n| auth_user_user_permissions |\n| django_admin_log           |\n| django_content_type        |\n| django_migrations          |\n| django_session             |\n| myapp2_testapp             |\n+----------------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

追溯:

\n\n
---------------------------------------------------------------------------\nProgrammingError                          Traceback (most recent call last)\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)\n     83             else:\n---> 84                 return self.cursor.execute(sql, params)\n     85 \n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/mysql/base.py in execute(self, query, args)\n     70             # args is None means no string interpolation\n---> 71             return self.cursor.execute(query, args)\n     72         except Database.OperationalError as e:\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/cursors.py in execute(self, query, args)\n    208         assert isinstance(query, (bytes, bytearray))\n--> 209         res = self._query(query)\n    210         return res\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/cursors.py in _query(self, q)\n    314         self._result = None\n--> 315         db.query(q)\n    316         self._do_get_result(db)\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/connections.py in query(self, query)\n    225             query = bytes(query)\n--> 226         _mysql.connection.query(self, query)\n    227 \n\nProgrammingError: (1146, "Table \'test.myapp_testdefault\' doesn\'t exist")\n\nThe above exception was the direct cause of the following exception:\n\nProgrammingError                          Traceback (most recent call last)\n<ipython-input-22-da112720c459> in <module>\n----> 1 user.delete()\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/base.py in delete(self, using, keep_parents)\n    916 \n    917         collector = Collector(using=using)\n--> 918         collector.collect([self], keep_parents=keep_parents)\n    919         return collector.delete()\n    920 \n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/deletion.py in collect(self, objs, source, nullable, collect_related, source_attr, reverse_dependency, keep_parents)\n    221                     if self.can_fast_delete(sub_objs, from_field=field):\n    222                         self.fast_deletes.append(sub_objs)\n--> 223                     elif sub_objs:\n    224                         field.remote_field.on_delete(self, field, sub_objs, self.using)\n    225             for field in model._meta.private_fields:\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/query.py in __bool__(self)\n    276 \n    277     def __bool__(self):\n--> 278         self._fetch_all()\n    279         return bool(self._result_cache)\n    280 \n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/query.py in _fetch_all(self)\n   1240     def _fetch_all(self):\n   1241         if self._result_cache is None:\n-> 1242             self._result_cache = list(self._iterable_class(self))\n   1243         if self._prefetch_related_lookups and not self._prefetch_done:\n   1244             self._prefetch_related_objects()\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/query.py in __iter__(self)\n     53         # Execute the query. This will also fill compiler.select, klass_info,\n     54         # and annotations.\n---> 55         results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)\n     56         select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info,\n     57                                                   compiler.annotation_col_map)\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py in execute_sql(self, result_type, chunked_fetch, chunk_size)\n   1098             cursor = self.connection.cursor()\n   1099         try:\n-> 1100             cursor.execute(sql, params)\n   1101         except Exception:\n   1102             # Might fail for server-side cursors (e.g. connection closed)\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in execute(self, sql, params)\n     97         start = time()\n     98         try:\n---> 99             return super().execute(sql, params)\n    100         finally:\n    101             stop = time()\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in execute(self, sql, params)\n     65 \n     66     def execute(self, sql, params=None):\n---> 67         return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)\n     68 \n     69     def executemany(self, sql, param_list):\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in _execute_with_wrappers(self, sql, params, many, executor)\n     74         for wrapper in reversed(self.db.execute_wrappers):\n     75             executor = functools.partial(wrapper, executor)\n---> 76         return executor(sql, params, many, context)\n     77 \n     78     def _execute(self, sql, params, *ignored_wrapper_args):\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)\n     82                 return self.cursor.execute(sql)\n     83             else:\n---> 84                 return self.cursor.execute(sql, params)\n     85 \n     86     def _executemany(self, sql, param_list, *ignored_wrapper_args):\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/utils.py in __exit__(self, exc_type, exc_value, traceback)\n     87                 if dj_exc_type not in (DataError, IntegrityError):\n     88                     self.wrapper.errors_occurred = True\n---> 89                 raise dj_exc_value.with_traceback(traceback) from exc_value\n     90 \n     91     def __call__(self, func):\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/utils.py in _execute(self, sql, params, *ignored_wrapper_args)\n     82                 return self.cursor.execute(sql)\n     83             else:\n---> 84                 return self.cursor.execute(sql, params)\n     85 \n     86     def _executemany(self, sql, param_list, *ignored_wrapper_args):\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/django/db/backends/mysql/base.py in execute(self, query, args)\n     69         try:\n     70             # args is None means no string interpolation\n---> 71             return self.cursor.execute(query, args)\n     72         except Database.OperationalError as e:\n     73             # Map some error codes to IntegrityError, since they seem to be\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/cursors.py in execute(self, query, args)\n    207 \n    208         assert isinstance(query, (bytes, bytearray))\n--> 209         res = self._query(query)\n    210         return res\n    211 \n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/cursors.py in _query(self, q)\n    313         db = self._get_db()\n    314         self._result = None\n--> 315         db.query(q)\n    316         self._do_get_result(db)\n    317         self._post_get_result()\n\n~/projects/learn-some/learn-some-django/test/.venv/lib/python3.7/site-packages/MySQLdb/connections.py in query(self, query)\n    224         if isinstance(query, bytearray):\n    225             query = bytes(query)\n--> 226         _mysql.connection.query(self, query)\n    227 \n    228     def _bytes_literal(self, bs):\n\nProgrammingError: (1146, "Table \'test.myapp_testdefault\' doesn\'t exist")\n
Run Code Online (Sandbox Code Playgroud)\n\n

testdefault它表明django尝试在数据库中的表中查找记录test。显然这是不可能的。它为什么要尝试这样做?在这种情况下删除用户的正确方法是什么\xef\xbc\x9f

\n

小智 0

using使用模型的方法删除时,可以使用参数指定要删除的数据库delete()

这就是混乱的根源:

查询集 delete方法不接受任何参数,如文档中所示:

删除()

对 QuerySet 中的所有行执行 SQL 删除查询,并返回已删除的对象数以及包含每种对象类型的删除数的字典。

模型的 delete方法接受using参数:

Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)

为对象发出 SQL DELETE。这只会删除数据库中的对象;Python 实例仍然存在,并且其字段中仍然有数据。此方法返回已删除的对象数量以及包含每种对象类型的删除数量的字典。

我希望这对那些在相同情况下感到有点困惑的人有所帮助:具有活动数据库路由器的多个数据库以及看似错误的内容被删除。