2015-07-21 68 views
7

在一個Django 1.8的項目,我有一個遷移是工作正常,when it had the following codeDjango遷移失敗,並顯示「__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), 
    ] 

這個小組在遷移創建,因爲它應是在Web應用程序的所有安裝使用。爲了使它更實用,我想也給它一個默認的權限,所以我改變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)工作,遷移與此和所有其他遷移(python3 manage.py migrate),新創建的PostgreSQL數據庫失敗:

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

啊,所以權限是在* all * migrations之後創建的,而不是在每個個人*遷移之後創建的。 –

+0

每次執行manage.py migrate命令時都會觸發'post_migrate'信號 - 所以是的,如果您一次應用所有遷移,它將在_all_遷移運行後觸發。 – knbk

+0

此答案有此解決方法: http://stackoverflow.com/questions/31735042/adding-django-admin-permissions-in-a-migration-permission-matching-query-does-n –