Reputation: 5650
I'm using Django (1.9.6)
, pytest (2.9.2)
and pytest-django (2.9.1)
I have a data migration that looks like this:
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-07 09:56
from __future__ import unicode_literals
from django.db import migrations
def create_groups(apps, schema_editor):
Group = apps.get_model('auth', 'group')
Permission = apps.get_model('auth', 'permission')
group1 = Group.objects.create(name='grou1')
group1_permissions = Permission.objects.filter(codename__in=[
'add_app1_model',
'add_app2_model',
'custom_permission_app1_model'
])
group1.permissions.add(*list(group1_permissions))
group2 = Group.objects.create(name='group2')
group2_permissions = Permission.objects.get(
codename='custom_permission_app2_model'
)
group2.permissions.add(*list(group2_permissions))
class Migration(migrations.Migration):
dependencies = [
('app1', '0001'),
('app2', '0001')
]
operations = [
migrations.RunPython(create_groups)
]
When I execute py.test --create-db
all the tests that are marked with pytest.mark.django_db
are raising __fake__.DoesNotExist: Permission matching query does not exist.
in the get
operation of the migration.
Debuging the migrations I found out that the create
operations work, but the filter
operation always returns empty, my test database has the groups created but no permission is associated to any of the groups.
I don't know if I'm doing something wrong? The temporary fix I did was changing the get
to filter
, this make the migration execute normally. In the tests I have a fixture that assigns to a user the permissions needed. Because all my code checks against the permissions and not if the user belongs to a groups all my tests pass.
Upvotes: 1
Views: 2182
Reputation: 5650
I found the solution thanks to @Håken Lid and the Django issue he provided. The problem is that Django creates the ContentTypes receiving a signal emitted when all the migrations complete. That's why it didn't find the permissions but it let me create the groups.
To solve the problem we have to manually send the signal inside our data migration.
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-06-07 09:56
from __future__ import unicode_literals
from django.core.management.sql import emit_post_migrate_signal
from django.db import migrations
def create_groups(apps, schema_editor):
# Send the signal to create the permissions
db_alias = schema_editor.connection.alias
try:
# Django 1.9
emit_post_migrate_signal(2, False, db_alias)
except TypeError:
# Django < 1.9
try:
# Django 1.8
emit_post_migrate_signal(2, False, 'default', db_alias)
except TypeError: # Django < 1.8
emit_post_migrate_signal([], 2, False, 'default', db_alias)
Group = apps.get_model('auth', 'group')
Permission = apps.get_model('auth', 'permission')
group1 = Group.objects.create(name='grou1')
group1_permissions = Permission.objects.filter(codename__in=[
'add_app1_model',
'add_app2_model',
'custom_permission_app1_model'
])
group1.permissions.add(*list(group1_permissions))
group2 = Group.objects.create(name='group2')
group2_permissions = Permission.objects.get(
codename='custom_permission_app2_model'
)
group2.permissions.add(*list(group2_permissions))
class Migration(migrations.Migration):
dependencies = [
('app1', '0001'),
('app2', '0001'),
('contenttypes', '__latest__'),
('sites', '__latest__')
]
operations = [
migrations.RunPython(create_groups)
]
In the snipped we send the signal before accessing the Permissions and we include the latest contenttypes
and sites
apps migrations as dependencies.
Upvotes: 2