2014-10-22 15 views
23

Quando cambio help_text o verbose_name per uno qualsiasi dei miei campi modello ed eseguo python manage.py makemigrations, esso rileva queste modifiche e crea una nuova migrazione, ad esempio 0002_xxxx.py.Perché Django esegue migrazioni per le modifiche help_text e verbose_name?

Sto usando PostgreSQL e penso che queste modifiche siano irrilevanti per il mio database (mi chiedo se esiste un DBMS per il quale queste modifiche sono rilevanti).

Perché Django genera migrazioni per tali modifiche? È un'opzione per ignorarli?

È possibile applicare le modifiche da 0002_xxxx.py alla migrazione precedente (0001_initial.py) manualmente e in modo sicuro per eliminare 0002_xxxx.py?

C'è un modo per aggiornare automaticamente la migrazione precedente?

+2

Questo commento dal andrewgodwin risponde alla domanda in parte, ma Voglio comunque poter modificare 'help_text' senza dover aggiornare le migrazioni: https://code.djangoproject.com/ticket/21498#comment:6 – utapyngo

risposta

7

This ticket ha risolto il problema.

Se è stato modificato solo help_text & django genera una nuova migrazione; quindi è possibile applicare le modifiche dall'ultima migrazione alla migrazione precedente ed eliminare la migrazione più recente.

Basta cambiare il help_text nella migrazione precedente per help_text presente nella migrazione più recente ed eliminare il file di migrazione più recente. Assicurati di rimuovere il file *.pyc corrispondente se è presente. Altrimenti verrà sollevata un'eccezione.

4

Per evitare migrazioni inutili si può fare come segue:

  1. campo sottoclasse che provoca la migrazione
  2. Scrivi personalizzato decostruire metodo all'interno di quel campo
  3. Profit

Esempio:

from django.db import models 

class CustomCharField(models.CharField): # or any other field 

    def deconstruct(self): 
     name, path, args, kwargs = super(CustomCharField, self).deconstruct() 
     # exclude all fields you dont want to cause migration, my example below: 
     if 'help_text' in kwargs: 
      del kwargs['help_text'] 
     if 'verbose_name' in kwargs: 
      del kwargs['verbose_name'] 
     return name, path, args, kwargs 

Speranza che aiuti

1

Come @ChillarAnand ha notato che esiste un ticket per risolvere questo problema ma fino ad ora (django 1.9.1) i comandi di migrazione non erano corretti.

Il modo meno intrusivo di risolverlo è quello di creare il proprio maketranslatedmigrations comando nella <your-project>/management/commands/maketranslatedmigrations.py come

#coding: utf-8 

from django.core.management.base import BaseCommand 
from django.core.management.commands.makemigrations import Command as MakeMigrations 


class Command(MakeMigrations): 
    leave_locale_alone = True 
    can_import_settings = True 

    def handle(self, *app_labels, **options): 
     super(Command, self).handle(*app_labels, **options) 

e quindi è possibile usarlo esattamente come makemigrations originali.

P.S. Non dimenticate di aggiungere __init__.py file ovunque sul percorso

+0

La domanda originale riguardava' makemigrations', non 'maketranslations'. – utapyngo

+0

Grazie per aver segnalato il mio errore di battitura – katomaso

0

ho scritto modulo personalizzato a tal fine

Tutto ciò che serve è quello di salvarlo in alcuni utils/modelli.db e in tutti i vostri modelli anziché from django.db import models scrittura from utils import models

Se qualcuno è interessato a che posso scrivere un componente e pubblicarlo sul PyPI

UPD: provare questo https://github.com/FeroxTL/django-migration-control

# models.py

# -*- coding: utf-8 -*- 
from types import FunctionType 
from django.db import models 


class NoMigrateMixin(object): 
    """ 
    Позволяет исключить из миграций различные поля 
    """ 
    def deconstruct(self): 
     name, path, args, kwargs = super(NoMigrateMixin, self).deconstruct() 
     kwargs.pop('help_text', None) 
     kwargs.pop('verbose_name', None) 
     return name, path, args, kwargs 


# ============================================================================= 
# DJANGO CLASSES 
# ============================================================================= 

for name, cls in models.__dict__.items(): 
    if isinstance(cls, type): 
     if issubclass(cls, models.Field): 
      # Поля 
      globals()[name] = type(name, (NoMigrateMixin, cls), {}) 
     else: 
      # Всякие менеджеры 
      globals()[name] = cls 
    elif isinstance(cls, FunctionType): 
     # Прочие функции 
     globals()[name] = cls 
8

È possibile squash it with the previous migration, sicuro.

Oppure, se non si desidera attivare quelle migrazioni a tutti, è possibile ignorare il comando makemigrations e migrate mettendo questo in management/commands/makemigrations.py nella vostra applicazione:

from django.core.management.commands.makemigrations import Command 
from django.db import models 

IGNORED_ATTRS = ['verbose_name', 'help_text', 'choices'] 

original_deconstruct = models.Field.deconstruct 

def new_deconstruct(self): 
    name, path, args, kwargs = original_deconstruct(self) 
    for attr in IGNORED_ATTRS: 
    kwargs.pop(attr, None) 
    return name, path, args, kwargs 

models.Field.deconstruct = new_deconstruct 
+0

Grazie per aver segnalato questo! Sembra così ovvio dopo il fatto. Questa è una cosa filosofica per alcuni (migrazioni complete); è bello in teoria, tranne che non funziona nella pratica. Soprattutto con help_text, scelte e 'storage'! Il nostro gestore e percorso di memorizzazione è determinato in fase di esecuzione, quindi ... cosa vuoi che io faccia uno storage falso per le migrazioni? Gah. Questo lo risolve ... separa le preoccupazioni di runtime dalle preoccupazioni del modello, come dovrebbe essere. –

Problemi correlati