数据迁移之Django pytest数据库访问
Django pytest database access for data migration
我正在使用 Django (1.9.6)
、pytest (2.9.2)
和 pytest-django (2.9.1)
我的数据迁移如下所示:
# -*- 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)
]
当我执行 py.test --create-db
时,所有标有 pytest.mark.django_db
的测试都在迁移的 get
操作中引发 __fake__.DoesNotExist: Permission matching query does not exist.
。
调试迁移我发现 create
操作有效,但 filter
操作总是 returns 空,我的测试数据库创建了组,但没有关联权限任何组。
不知道我是不是做错了什么?我所做的临时修复是将 get
更改为 filter
,这使迁移正常执行。在测试中,我有一个固定装置可以为用户分配所需的权限。因为我所有的代码都检查权限,而不检查用户是否属于某个组,所以我的所有测试都通过了。
感谢@Håken Lid 和他提供的 Django issue,我找到了解决方案。问题是 Django 创建的 ContentTypes 接收所有迁移完成时发出的信号。这就是为什么它没有找到权限,但它让我创建了组。
为了解决这个问题,我们必须在数据迁移中手动发送信号。
# -*- 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)
]
在片段中,我们在访问权限之前发送信号,我们将最新的 contenttypes
和 sites
应用程序迁移作为依赖项。
我正在使用 Django (1.9.6)
、pytest (2.9.2)
和 pytest-django (2.9.1)
我的数据迁移如下所示:
# -*- 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)
]
当我执行 py.test --create-db
时,所有标有 pytest.mark.django_db
的测试都在迁移的 get
操作中引发 __fake__.DoesNotExist: Permission matching query does not exist.
。
调试迁移我发现 create
操作有效,但 filter
操作总是 returns 空,我的测试数据库创建了组,但没有关联权限任何组。
不知道我是不是做错了什么?我所做的临时修复是将 get
更改为 filter
,这使迁移正常执行。在测试中,我有一个固定装置可以为用户分配所需的权限。因为我所有的代码都检查权限,而不检查用户是否属于某个组,所以我的所有测试都通过了。
感谢@Håken Lid 和他提供的 Django issue,我找到了解决方案。问题是 Django 创建的 ContentTypes 接收所有迁移完成时发出的信号。这就是为什么它没有找到权限,但它让我创建了组。
为了解决这个问题,我们必须在数据迁移中手动发送信号。
# -*- 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)
]
在片段中,我们在访问权限之前发送信号,我们将最新的 contenttypes
和 sites
应用程序迁移作为依赖项。