2015-07-21 6 views
7

В 1.8 проекта Django, у меня есть миграции, которая работала хорошо, when it had the following code:Миграция Django не выполняется с помощью «__fake __. DoesNotExist: запрос соответствия разрешения не существует».

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 

from django.db import migrations 
from django.conf import settings 


def update_site_forward(apps, schema_editor): 
    """Add group osmaxx.""" 
    Group = apps.get_model("auth", "Group") 
    Group.objects.create(name=settings.OSMAXX_FRONTEND_USER_GROUP) 


def update_site_backward(apps, schema_editor): 
    """Revert add group osmaxx.""" 
    Group = apps.get_model("auth", "Group") 
    Group.objects.get(name=settings.OSMAXX_FRONTEND_USER_GROUP).delete() 


class Migration(migrations.Migration): 

    dependencies = [ 
     ('auth', '0001_initial'), 
    ] 

    operations = [ 
     migrations.RunPython(update_site_forward, update_site_backward), 
    ] 

Эта группа создается в миграции, так как она должна быть доступна во всех установках веб-приложения. Для того, чтобы сделать его более полезным, я хотел бы также дать ему разрешение по умолчанию, так что я изменил update_site_forward на:

def update_site_forward(apps, schema_editor): 
    """Add group osmaxx.""" 
    Group = apps.get_model("auth", "Group") 
    Permission = apps.get_model("auth", "Permission") 
    ContentType = apps.get_model("contenttypes", "ContentType") 
    ExtractionOrder = apps.get_model("excerptexport", "ExtractionOrder") 
    group = Group.objects.create(name=settings.OSMAXX_FRONTEND_USER_GROUP) 
    content_type = ContentType.objects.get_for_model(ExtractionOrder) 
    permission = Permission.objects.get(codename='add_extractionorder', 
             content_type=content_type) # line 16 
    group.permissions.add(permission) 

и Migration.dependencies к:

dependencies = [ 
     ('contenttypes', '0002_remove_content_type_name'), 
     ('excerptexport', '0001_initial'), 
     ('auth', '0001_initial'), 
    ] 

При применении миграции (после первого возвращаясь она) (python3 manage.py migrate auth 0001 && python3 managy.py migrate) работал, миграции вновь созданную базу данных PostgreSQL с этим и всех других миграций (python3 manage.py migrate) не:

Operations to perform: 
    Synchronize unmigrated apps: debug_toolbar, django_extensions, messages, humanize, social_auth, kombu_transport_django, staticfiles 
    Apply all migrations: excerptexport, admin, sites, contenttypes, sessions, default, stored_messages, auth 
Synchronizing apps without migrations: 
    Creating tables... 
    Running deferred SQL... 
    Installing custom SQL... 
Running migrations: 
    Rendering model states... DONE 
    Applying auth.0002_add_default_usergroup_osmaxx...Traceback (most recent call last): 
    File "manage.py", line 17, in <module> 
    execute_from_command_line(sys.argv) 
    File "/usr/local/lib/python3.4/dist-packages/django/core/management/__init__.py", line 338, in execute_from_command_line 
    utility.execute() 
    File "/usr/local/lib/python3.4/dist-packages/django/core/management/__init__.py", line 330, in execute 
    self.fetch_command(subcommand).run_from_argv(self.argv) 
    File "/usr/local/lib/python3.4/dist-packages/django/core/management/base.py", line 393, in run_from_argv 
    self.execute(*args, **cmd_options) 
    File "/usr/local/lib/python3.4/dist-packages/django/core/management/base.py", line 444, in execute 
    output = self.handle(*args, **options) 
    File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/migrate.py", line 221, in handle 
    executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/executor.py", line 110, in migrate 
    self.apply_migration(states[migration], migration, fake=fake, fake_initial=fake_initial) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/executor.py", line 148, in apply_migration 
    state = migration.apply(state, schema_editor) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/migration.py", line 115, in apply 
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/operations/special.py", line 183, in database_forwards 
    self.code(from_state.apps, schema_editor) 
    File "/home/osmaxx/source/osmaxx/contrib/auth/migrations/0002_add_default_usergroup_osmaxx.py", line 16, in update_site_forward 
    permission = Permission.objects.get(codename='add_extractionorder', content_type=content_type) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/models/manager.py", line 127, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/usr/local/lib/python3.4/dist-packages/django/db/models/query.py", line 334, in get 
    self.model._meta.object_name 
__fake__.DoesNotExist: Permission matching query does not exist. 

Что я делаю неправильно?

+0

Примечание: полный код проекта (без упомянутого изменения) доступен [на GitHub] (https://github.com/geometalab/osmaxx/tree/378ddc5043f1fd80727067de19316f30d1f725b5). Указанная миграция - [osmaxx-py/osmaxx/contrib/auth/migrations/0002_add_default_usergroup_osmaxx.py] (https://github.com/geometalab/osmaxx/blob/378ddc5043f1fd80727067de19316f30d1f725b5/osmaxx-py/osmaxx/contrib/auth/migrations/ 0002_add_default_usergroup_osmaxx.py) Но, пожалуйста, прокомментируйте, если что-то там, но не упомянутое в вопросе, имеет значение для ответа на вопрос, чтобы я мог включить его в вопрос. –

ответ

10

Разрешения по умолчанию создаются в обработчике сигнала post_migrate, после миграции выполнялись. Это не будет проблемой, если ваш обновленный код работает как часть второго запуска manage.py migrate, но это проблема в наборе тестов и любом новом развертывании.

Простое исправление, чтобы изменить эту строку:

permission = Permission.objects.get(codename='add_extractionorder', 
            content_type=content_type) # line 16 

к этому:

permission, created = Permission.objects.get_or_create(codename='add_extractionorder', 
               content_type=content_type) 

обработчик сигналов, который создает права доступа по умолчанию никогда не будет создавать дубликат разрешения, так что это безопасно создайте его, если он уже не существует.

+0

А, так что разрешения создаются после * всех * миграций, а не после * каждой индивидуальной миграции? –

+0

Сигнал 'post_migrate' срабатывает каждый раз, когда команда' manage.py migrate' завершается - так что да, если вы применяете все миграции одновременно, он запускается после запуска _all_ миграции. – knbk

+0

Этот ответ обходной путь для этого: http://stackoverflow.com/questions/31735042/adding-django-admin-permissions-in-a-migration-permission-matching-query-does-n –