Reputation: 439
I have a bunch of new permissions which I need to migrate. I tried doing it through data migration but complains about ContentType not being available
.
Doing quick research I found out that ContentType
table is populated after all the migrations applied.
I even tried using update_all_contenttypes()
from from django.contrib.contenttypes.management import update_all_contenttypes
which causes migration to load data which is not consistent to the fixture.
What is the best way to migrate permission data in Django?
Upvotes: 8
Views: 8599
Reputation: 6105
Here is a quick and dirty way to ensure all permissions for all apps have been created:
def add_all_permissions(apps=None, schema_editor=None):
from django.contrib.auth.management import create_permissions
if apps is None:
from django.apps import apps
for app_config in apps.get_app_configs():
app_config.models_module = True
create_permissions(app_config, verbosity=0)
app_config.models_module = None
class Migration(migrations.Migration):
dependencies = [('myapp', '0123_do_the_thing')]
operations = [
migrations.RunPython(add_all_permissions,
reverse_code=migrations.RunPython.noop)
# ...
]
NOTE: edited to include ruohola's excellent suggestion
Upvotes: 11
Reputation: 9675
There are 2 ways to solve this:
1) The ugly way:
Run manage.py migrate auth
before your wanted migration
2) Recommended way:
from django.contrib.auth.management import create_permissions
def add_permissions(apps, schema_editor):
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
# rest of code here....
Upvotes: 12
Reputation: 10680
Here are steps for adding custom permissions to the User
model:
First create a migration file, for example under your authentication application,
Here i named it 0002_permission_fixtures.py
:
account (your authentication application)
|_migrations
|__ 0001_initial.py
|__ 0002_permission_fixtures.py
|__ __init__.py
Then adding your permission objects, as follow:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def forwards_func(apps, schema_editor):
# Get models that we needs them
user = apps.get_model("auth", "User")
permission = apps.get_model("auth", "Permission")
content_type = apps.get_model("contenttypes", "ContentType")
# Get user content type object
uct = content_type.objects.get_for_model(user)
db_alias = schema_editor.connection.alias
# Adding your custom permissions to User model:
permission.objects.using(db_alias).bulk_create([
permission(codename='add_sample', name='Can add sample', content_type=uct),
permission(codename='change_sample', name='Can change sample', content_type=uct),
permission(codename='delete_sample', name='Can delete sample', content_type=uct),
])
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '__latest__'),
]
operations = [
migrations.RunPython(
forwards_func,
),
]
To run this migration, first migrate contenttype
model, and then migrate your application (here is account).
$ python manage.py migrate contenttypes
$ python manage.py migrate account
Upvotes: 5