1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
from django.db import models
from django.db.migrations.operations import AlterField
from .compat import get_apps_from_state, get_field, get_rel
class AlterSortedManyToManyField(AlterField):
"""A migration operation to transform a ManyToManyField into a
SortedManyToManyField and vice versa."""
def database_forwards(self, app_label, schema_editor, from_state, to_state):
to_apps = get_apps_from_state(to_state)
to_model = to_apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
to_field = get_field(to_model, self.name)
from_apps = get_apps_from_state(from_state)
from_model = from_apps.get_model(app_label, self.model_name)
from_field = get_field(from_model, self.name)
to_m2m_model = get_rel(to_field).through
from_m2m_model = get_rel(from_field).through
# M2M -> SortedM2M
if getattr(to_field, 'sorted', False):
self.add_sort_value_field(schema_editor, to_m2m_model)
# SortedM2M -> M2M
elif getattr(from_field, 'sorted', False):
self.remove_sort_value_field(schema_editor, from_m2m_model)
else:
raise TypeError(
'{operation} should only be used when changing a '
'SortedManyToManyField into a ManyToManyField or a '
'ManyToManyField into a SortedManyToManyField.'
.format(operation=self.__class__.__name__))
def database_backwards(self, app_label, schema_editor, from_state, to_state):
from_apps = get_apps_from_state(from_state)
from_model = from_apps.get_model(app_label, self.model_name)
from_field = get_field(from_model, self.name)
to_apps = get_apps_from_state(to_state)
to_model = to_apps.get_model(app_label, self.model_name)
if self.allow_migrate_model(schema_editor.connection.alias, to_model):
to_field = get_field(to_model, self.name)
from_m2m_model = get_rel(from_field).through
to_m2m_model = get_rel(to_field).through
# The `to_state` is the OLDER state.
# M2M -> SortedM2M (backwards)
if getattr(to_field, 'sorted', False):
self.add_sort_value_field(schema_editor, to_m2m_model)
# SortedM2M -> M2M (backwards)
elif getattr(from_field, 'sorted', False):
self.remove_sort_value_field(schema_editor, from_m2m_model)
else:
raise TypeError(
'{operation} should only be used when changing a '
'SortedManyToManyField into a ManyToManyField or a '
'ManyToManyField into a SortedManyToManyField.'
.format(operation=self.__class__.__name__))
def add_sort_value_field(self, schema_editor, model):
field = self.make_sort_by_field(model)
schema_editor.add_field(model, field)
def remove_sort_value_field(self, schema_editor, model):
field = get_field(model, model._sort_field_name)
schema_editor.remove_field(model, field)
def make_sort_by_field(self, model):
field_name = model._sort_field_name
field = models.IntegerField(name=field_name, default=0)
field.set_attributes_from_name(field_name)
return field
|