'Django manual migration to add group
I am attempting to create a migration that will automatically add a group and permissions to the group when it is run. I adapted some code from the docs and an example. I can get the migration to add the group but not the permissions. I am getting the following error: TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use permissions.set() instead.
I am not sure how to implement this suggestion. Any ideas?
The migration:
from django.db import migrations, models
from django.contrib.auth.models import Group, Permission
from django.contrib.auth.management import create_permissions
def add_group_permissions(apps, schema_editor):
for app_config in apps.get_app_configs():
create_permissions(app_config, apps=apps, verbosity=0)
# Employee
group, created = Group.objects.get_or_create(name='Employee')
if created:
permissions_qs = Permission.objects.filter(
codename__in=[
'can_add_how_to_entry',
'can_change_how_to_entry',
'can_view_how_to_entry',
]
)
group.permissions = permissions_qs
group.save()
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.RunPython(add_group_permissions),
]
Solution 1:[1]
Remember that group.permissions is a related query manager, not a field, so if you assign something to that you will destroy it. So you need to do something like:
permissions_qs = Permission.objects ...
for permission in permissions_qs:
group.permissions.add(permission)
group.save()
Additionally, the Django way to create custom permission is through the Meta class, for example:
# Assuming that you have an "Entry" model
class Entry(models.Model):
...
class Meta:
...
permissions = [
('custom_permission_a', 'a description for permission a'),
('custom_permission_b', 'a description for permission b'),
]
After migrating the changes you will have two additional permissions attached to the Entry model.
Now you can create a group with the custom permissions like:
group, created = Group.objects.get_or_create(name='CustomGroup')
if created:
permissions = Permission.objects.filter(
codename__in=[
'custom_permission_a',
'custom_permission_b',
]
)
for p in permissions:
group.permissions.add(p)
group.save()
You can include that in a new migration or whatever you want, also if you don't want to use the Meta class to create your custom permissions, you can do it programmatically:
# Assuming that you have an Entry model
# Import Entry model
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
entryContentType = ContentType.objects.get_for_model(Entry)
# Create custom permission
custom_permission = Permission.objects.create(
codename ='custom_permission',
name ='description for the custom permission',
content_type = entryContentType
)
A custom_permission will be created and attached to the Entry model. Then you can include that permission in your custom group.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
