python - Django 自定义迁移回滚
问题描述
我有以下自定义 Django 迁移代码:
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.core.management.sql import emit_post_migrate_signal
from django.db import migrations
def create_user_groups_permissions(apps, schema_editor):
emit_post_migrate_signal(verbosity=1, interactive=False, db='default')
Group = apps.get_model('auth', 'Group')
Permission = apps.get_model('auth', 'Permission')
User = apps.get_model('users', 'User')
Token = apps.get_model('authtoken', 'Token')
# Create the default superuser for development
defaults = {
'is_active': True,
'is_staff': True,
'is_superuser': True,
'email': settings.SERVER_EMAIL,
}
admin, _ = User.objects.get_or_create(username='admin', defaults=defaults)
if settings.ADMIN_PASSWORD_DEV:
admin.password = make_password(settings.ADMIN_PASSWORD_DEV)
admin.save()
# Create DRF token for admin
_, created = Token.objects.get_or_create(user=admin)
# Get permissions
can_upload_data = Permission.objects.get(codename='can_upload_data')
# Create groups with permissions
default_user, created = Group.objects.get_or_create(name='default_user')
if created:
default_user.permissions.add(can_upload_data)
def remove_user_groups_permissions(apps, schema_editor):
emit_post_migrate_signal(verbosity=1, interactive=False, db='default')
Group = apps.get_model('auth', 'Group')
Permission = apps.get_model('auth', 'Permission')
User = apps.get_model('users', 'User')
Token = apps.get_model('authtoken', 'Token')
# Delete DRF token for default superuser
Token.objects.filter(user__username='admin').delete()
# Get permissions
can_upload_data = Permission.objects.get(codename='can_upload_data')
# Delete permissions from groups
default_user = Group.objects.get(name='default_user')
default_user.permissions.remove(can_upload_data)
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.RunPython(code=create_user_groups_permissions, reverse_code=remove_user_groups_permissions),
]
向前迁移很好。但是,当我尝试回滚此迁移时,出现以下错误:
...
File "/usr/local/lib/python3.9/site-packages/django/db/migrations/operations/special.py", line 196, in database_backwards
self.reverse_code(from_state.apps, schema_editor)
File "/the_project_name/main_site/users/migrations/0002_fixtures_groups_permissions.py", line 92, in remove_user_groups_permissions
default_user.permissions.remove(can_upload_data)
File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 950, in remove
self._remove_items(self.source_field_name, self.target_field_name, *objs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 1129, in _remove_items
self.through._default_manager.using(db).filter(filters).delete()
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 892, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1290, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1310, in _add_q
child_clause, needed_inner = self._add_q(
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1315, in _add_q
child_clause, needed_inner = self.build_filter(
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1224, in build_filter
self.check_related_objects(join_info.final_field, value, join_info.opts)
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1087, in check_related_objects
self.check_query_object_type(v, opts, field)
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1065, in check_query_object_type
raise ValueError(
ValueError: Cannot query "Permission object (51)": Must be "Permission" instance.
我不明白这个错误,因为我在 .remove() 方法中传递了一个 Permission 实例,而不是一个字符串。我尝试过用 .filter() 后跟 .get() 替换 .get() 方法。我还在 .remove() 之前放置了一个断点() 以确保类型匹配,并且 can_upload_data 确实是一种类型,而解释器仍然吐出上述错误,表明它是一个字符串。有任何想法吗?
解决方案
因此,在修整了几个小时之后,我发现出于某种原因,在这种情况下 .remove() 方法需要一个想要删除的权限的 ID,而不是权限的实例。
奇怪,但它奏效了。也许是一个错误?我将把它复制到 Django 的 github 问题上进行检查。
Django 版本 2.2.23。
推荐阅读
- cakephp - CakePHP 3 - 在 table 对象中默认使用 select() 中的 SQL 函数
- javascript - Angular如何使用点击功能根据国家名称提取和显示特定的JSON数据
- python - 在 django 中编辑个人资料
- arrays - 如何获取 id 列表以使用 Angular 中的逗号字符串对象
- azure-devops - VSTS 仪表板中的周期和提前期小部件
- css - 如何调整离子旋转器的大小
- flutter - 即使流正在返回对象,Flutter StreamProvider也会返回空对象
- python - django随着时间的推移开发数据
- webpack - Webpack 4 - 文件加载器 - 不使用 @font-face 渲染字体(但构建并且一切正常)
- lucene - Lucene 中整数字段上的 Range Facet