2015-07-21 15 views
7

In un progetto di 1,8 Django, ho una migrazione che funzionava bene, when it had the following code:La migrazione di Django non riesce con "__fake __. DoesNotExist: la query di corrispondenza di autorizzazione non esiste."

# -*- 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), 
    ] 

Questo gruppo è stato creato in una migrazione, in quanto deve essere disponibile in tutte le installazioni di app web. Per renderlo più utile, ho voluto dare anche un permesso di default, così ho cambiato update_site_forward a:

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) 

e Migration.dependencies a:

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

Durante l'applicazione della migrazione (dopo il primo ripristino di esso) (python3 manage.py migrate auth 0001 && python3 managy.py migrate) ha lavorato, la migrazione di un database PostgreSQL appena creato con questo e tutti gli altri migrazioni (python3 manage.py migrate) fallisce:

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. 

Cosa sto sbagliando?

+0

Nota: il codice completo del progetto (senza la modifica menzionata) è disponibile [su GitHub] (https://github.com/geometalab/osmaxx/tree/378ddc5043f1fd80727067de19316f30d1f725b5). La migrazione menzionata è [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) Ma per favore commenta, se c'è qualcosa che non è menzionato nella domanda è rilevante per rispondere alla domanda, in modo che io possa includerlo nella domanda. –

risposta

10

Le autorizzazioni predefinite vengono create in un gestore di segnale post_migrate, dopo le migrazioni sono state eseguite. Ciò non costituirà un problema se il codice aggiornato viene eseguito come parte della seconda esecuzione manage.py migrate, ma si tratta di un problema nella suite di test e in qualsiasi nuova distribuzione.

La soluzione semplice è quello di cambiare questa linea:

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

a questo:

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

Il gestore del segnale che crea le autorizzazioni predefinite non potrà mai creare un permesso duplicato, quindi è sicuro creala se non esiste già.

+0

Ah, quindi le autorizzazioni vengono create dopo le migrazioni * all *, non dopo * ogni singola migrazione *? –

+0

Il segnale 'post_migrate' si attiva ogni volta che viene completato il comando' manage.py migrate' - quindi sì, se si applicano tutte le migrazioni contemporaneamente, si attiva dopo l'esecuzione di tutte le migrazioni. – knbk

+0

Questa risposta ha una soluzione per questo: http://stackoverflow.com/questions/31735042/adding-django-admin-permissions-in-a-migration-permission-matching-query-does-n –

Problemi correlati