I have the following custom Django migration code:
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),
]
Forward migration is fine with it. However, when I try to rollback this migration I get the following error:
...
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.
I don`t understand this error, since I am passing a Permission instance in the .remove() method there, not a string. I have tried experimenting with replacing .get() method with .filter() followed by .get(). I have also placed a breakpoint() right before .remove() to make sure types matched up, and can_upload_data is indeed a type, while interpretter still spits out the above error suggesting it is a String. Any ideas?