Django pytest database access for data migration
Asked Answered
N

1

1

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.

Nightwear answered 8/6, 2016 at 8:32 Comment(1)
There are some suggestions of how to work around this problem in this django issue tracker discussion. code.djangoproject.com/ticket/23422Supply
N
2

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.

Nightwear answered 8/6, 2016 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.