Start adding operations that work and tests for them
This commit is contained in:
parent
264f8650e3
commit
d0ecefc2c9
|
@ -272,7 +272,7 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
"new_tablespace": self.quote_name(new_db_tablespace),
|
"new_tablespace": self.quote_name(new_db_tablespace),
|
||||||
})
|
})
|
||||||
|
|
||||||
def create_field(self, model, field, keep_default=False):
|
def add_field(self, model, field, keep_default=False):
|
||||||
"""
|
"""
|
||||||
Creates a field on a model.
|
Creates a field on a model.
|
||||||
Usually involves adding a column, but may involve adding a
|
Usually involves adding a column, but may involve adding a
|
||||||
|
@ -325,7 +325,7 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete_field(self, model, field):
|
def remove_field(self, model, field):
|
||||||
"""
|
"""
|
||||||
Removes a field from a model. Usually involves deleting a column,
|
Removes a field from a model. Usually involves deleting a column,
|
||||||
but for M2Ms may involve deleting a table.
|
but for M2Ms may involve deleting a table.
|
||||||
|
|
|
@ -73,7 +73,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
if restore_pk_field:
|
if restore_pk_field:
|
||||||
restore_pk_field.primary_key = True
|
restore_pk_field.primary_key = True
|
||||||
|
|
||||||
def create_field(self, model, field):
|
def add_field(self, model, field):
|
||||||
"""
|
"""
|
||||||
Creates a field on a model.
|
Creates a field on a model.
|
||||||
Usually involves adding a column, but may involve adding a
|
Usually involves adding a column, but may involve adding a
|
||||||
|
@ -89,7 +89,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
raise ValueError("You cannot add a null=False column without a default value on SQLite.")
|
raise ValueError("You cannot add a null=False column without a default value on SQLite.")
|
||||||
self._remake_table(model, create_fields=[field])
|
self._remake_table(model, create_fields=[field])
|
||||||
|
|
||||||
def delete_field(self, model, field):
|
def remove_field(self, model, field):
|
||||||
"""
|
"""
|
||||||
Removes a field from a model. Usually involves deleting a column,
|
Removes a field from a model. Usually involves deleting a column,
|
||||||
but for M2Ms may involve deleting a table.
|
but for M2Ms may involve deleting a table.
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
from .migration import Migration
|
from .migration import Migration
|
||||||
|
from .operations import *
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.utils.datastructures import SortedSet
|
from django.utils.datastructures import SortedSet
|
||||||
|
from django.db.migrations.state import ProjectState
|
||||||
|
|
||||||
|
|
||||||
class MigrationGraph(object):
|
class MigrationGraph(object):
|
||||||
|
@ -33,8 +34,10 @@ class MigrationGraph(object):
|
||||||
self.nodes[node] = implementation
|
self.nodes[node] = implementation
|
||||||
|
|
||||||
def add_dependency(self, child, parent):
|
def add_dependency(self, child, parent):
|
||||||
self.nodes[child] = None
|
if child not in self.nodes:
|
||||||
self.nodes[parent] = None
|
raise KeyError("Dependency references nonexistent child node %r" % (child,))
|
||||||
|
if parent not in self.nodes:
|
||||||
|
raise KeyError("Dependency references nonexistent parent node %r" % (parent,))
|
||||||
self.dependencies.setdefault(child, set()).add(parent)
|
self.dependencies.setdefault(child, set()).add(parent)
|
||||||
self.dependents.setdefault(parent, set()).add(child)
|
self.dependents.setdefault(parent, set()).add(child)
|
||||||
|
|
||||||
|
@ -117,6 +120,16 @@ class MigrationGraph(object):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Graph: %s nodes, %s edges" % (len(self.nodes), sum(len(x) for x in self.dependencies.values()))
|
return "Graph: %s nodes, %s edges" % (len(self.nodes), sum(len(x) for x in self.dependencies.values()))
|
||||||
|
|
||||||
|
def project_state(self, node):
|
||||||
|
"""
|
||||||
|
Given a migration node, returns a complete ProjectState for it.
|
||||||
|
"""
|
||||||
|
plan = self.forwards_plan(node)
|
||||||
|
project_state = ProjectState()
|
||||||
|
for node in plan:
|
||||||
|
project_state = self.nodes[node].mutate_state(project_state)
|
||||||
|
return project_state
|
||||||
|
|
||||||
|
|
||||||
class CircularDependencyError(Exception):
|
class CircularDependencyError(Exception):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
from django.utils.importlib import import_module
|
from django.utils.importlib import import_module
|
||||||
|
from django.utils.functional import cached_property
|
||||||
from django.db.models.loading import cache
|
from django.db.models.loading import cache
|
||||||
from django.db.migrations.recorder import MigrationRecorder
|
from django.db.migrations.recorder import MigrationRecorder
|
||||||
from django.db.migrations.graph import MigrationGraph
|
from django.db.migrations.graph import MigrationGraph
|
||||||
|
@ -64,9 +65,10 @@ class MigrationLoader(object):
|
||||||
migration_module = import_module("%s.%s" % (module_name, migration_name))
|
migration_module = import_module("%s.%s" % (module_name, migration_name))
|
||||||
if not hasattr(migration_module, "Migration"):
|
if not hasattr(migration_module, "Migration"):
|
||||||
raise BadMigrationError("Migration %s in app %s has no Migration class" % (migration_name, app_label))
|
raise BadMigrationError("Migration %s in app %s has no Migration class" % (migration_name, app_label))
|
||||||
self.disk_migrations[app_label, migration_name] = migration_module.Migration
|
self.disk_migrations[app_label, migration_name] = migration_module.Migration(migration_name, app_label)
|
||||||
|
|
||||||
def build_graph(self):
|
@cached_property
|
||||||
|
def graph(self):
|
||||||
"""
|
"""
|
||||||
Builds a migration dependency graph using both the disk and database.
|
Builds a migration dependency graph using both the disk and database.
|
||||||
"""
|
"""
|
||||||
|
@ -116,6 +118,7 @@ class MigrationLoader(object):
|
||||||
graph = MigrationGraph()
|
graph = MigrationGraph()
|
||||||
for key, migration in normal.items():
|
for key, migration in normal.items():
|
||||||
graph.add_node(key, migration)
|
graph.add_node(key, migration)
|
||||||
|
for key, migration in normal.items():
|
||||||
for parent in migration.dependencies:
|
for parent in migration.dependencies:
|
||||||
graph.add_dependency(key, parent)
|
graph.add_dependency(key, parent)
|
||||||
return graph
|
return graph
|
||||||
|
|
|
@ -10,6 +10,9 @@ class Migration(object):
|
||||||
- dependencies: A list of tuples of (app_path, migration_name)
|
- dependencies: A list of tuples of (app_path, migration_name)
|
||||||
- run_before: A list of tuples of (app_path, migration_name)
|
- run_before: A list of tuples of (app_path, migration_name)
|
||||||
- replaces: A list of migration_names
|
- replaces: A list of migration_names
|
||||||
|
|
||||||
|
Note that all migrations come out of migrations and into the Loader or
|
||||||
|
Graph as instances, having been initialised with their app label and name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Operations to apply during this migration, in order.
|
# Operations to apply during this migration, in order.
|
||||||
|
@ -28,3 +31,17 @@ class Migration(object):
|
||||||
# non-empty, this migration will only be applied if all these migrations
|
# non-empty, this migration will only be applied if all these migrations
|
||||||
# are not applied.
|
# are not applied.
|
||||||
replaces = []
|
replaces = []
|
||||||
|
|
||||||
|
def __init__(self, name, app_label):
|
||||||
|
self.name = name
|
||||||
|
self.app_label = app_label
|
||||||
|
|
||||||
|
def mutate_state(self, project_state):
|
||||||
|
"""
|
||||||
|
Takes a ProjectState and returns a new one with the migration's
|
||||||
|
operations applied to it.
|
||||||
|
"""
|
||||||
|
new_state = project_state.clone()
|
||||||
|
for operation in self.operations:
|
||||||
|
operation.state_forwards(self.app_label, new_state)
|
||||||
|
return new_state
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
from .models import CreateModel, DeleteModel
|
from .models import CreateModel, DeleteModel
|
||||||
|
from .fields import AddField, RemoveField
|
||||||
|
|
|
@ -15,21 +15,21 @@ class Operation(object):
|
||||||
# Some operations are impossible to reverse, like deleting data.
|
# Some operations are impossible to reverse, like deleting data.
|
||||||
reversible = True
|
reversible = True
|
||||||
|
|
||||||
def state_forwards(self, app, state):
|
def state_forwards(self, app_label, state):
|
||||||
"""
|
"""
|
||||||
Takes the state from the previous migration, and mutates it
|
Takes the state from the previous migration, and mutates it
|
||||||
so that it matches what this migration would perform.
|
so that it matches what this migration would perform.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def database_forwards(self, app, schema_editor, from_state, to_state):
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
"""
|
"""
|
||||||
Performs the mutation on the database schema in the normal
|
Performs the mutation on the database schema in the normal
|
||||||
(forwards) direction.
|
(forwards) direction.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def database_backwards(self, app, schema_editor, from_state, to_state):
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
"""
|
"""
|
||||||
Performs the mutation on the database schema in the reverse
|
Performs the mutation on the database schema in the reverse
|
||||||
direction - e.g. if this were CreateModel, it would in fact
|
direction - e.g. if this were CreateModel, it would in fact
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
from .base import Operation
|
||||||
|
|
||||||
|
|
||||||
|
class AddField(Operation):
|
||||||
|
"""
|
||||||
|
Adds a field to a model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, model_name, name, instance):
|
||||||
|
self.model_name = model_name
|
||||||
|
self.name = name
|
||||||
|
self.instance = instance
|
||||||
|
|
||||||
|
def state_forwards(self, app_label, state):
|
||||||
|
state.models[app_label, self.model_name.lower()].fields.append((self.name, self.instance))
|
||||||
|
|
||||||
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = to_state.render()
|
||||||
|
model = app_cache.get_model(app_label, self.name)
|
||||||
|
schema_editor.add_field(model, model._meta.get_field_by_name(self.name))
|
||||||
|
|
||||||
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = from_state.render()
|
||||||
|
model = app_cache.get_model(app_label, self.name)
|
||||||
|
schema_editor.remove_field(model, model._meta.get_field_by_name(self.name))
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveField(Operation):
|
||||||
|
"""
|
||||||
|
Removes a field from a model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, model_name, name):
|
||||||
|
self.model_name = model_name
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def state_forwards(self, app_label, state):
|
||||||
|
new_fields = []
|
||||||
|
for name, instance in state.models[app_label, self.model_name.lower()].fields:
|
||||||
|
if name != self.name:
|
||||||
|
new_fields.append((name, instance))
|
||||||
|
state.models[app_label, self.model_name.lower()].fields = new_fields
|
||||||
|
|
||||||
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = from_state.render()
|
||||||
|
model = app_cache.get_model(app_label, self.name)
|
||||||
|
schema_editor.remove_field(model, model._meta.get_field_by_name(self.name))
|
||||||
|
|
||||||
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = to_state.render()
|
||||||
|
model = app_cache.get_model(app_label, self.name)
|
||||||
|
schema_editor.add_field(model, model._meta.get_field_by_name(self.name))
|
|
@ -1,4 +1,5 @@
|
||||||
from .base import Operation
|
from .base import Operation
|
||||||
|
from django.db import models
|
||||||
from django.db.migrations.state import ModelState
|
from django.db.migrations.state import ModelState
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,20 +8,39 @@ class CreateModel(Operation):
|
||||||
Create a model's table.
|
Create a model's table.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name, fields, options=None, bases=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.fields = fields
|
||||||
|
self.options = options or {}
|
||||||
|
self.bases = bases or (models.Model,)
|
||||||
|
|
||||||
def state_forwards(self, app, state):
|
def state_forwards(self, app_label, state):
|
||||||
state.models[app, self.name.lower()] = ModelState(state, app, self.name)
|
state.models[app_label, self.name.lower()] = ModelState(app_label, self.name, self.fields, self.options, self.bases)
|
||||||
|
|
||||||
def database_forwards(self, app, schema_editor, from_state, to_state):
|
def database_forwards(self, app, schema_editor, from_state, to_state):
|
||||||
app_cache = to_state.render()
|
app_cache = to_state.render()
|
||||||
schema_editor.create_model(app_cache.get_model(app, self.name))
|
schema_editor.create_model(app_cache.get_model(app, self.name))
|
||||||
|
|
||||||
def database_backwards(self, app, schema_editor, from_state, to_state):
|
def database_backwards(self, app, schema_editor, from_state, to_state):
|
||||||
|
app_cache = from_state.render()
|
||||||
|
schema_editor.delete_model(app_cache.get_model(app, self.name))
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteModel(Operation):
|
||||||
"""
|
"""
|
||||||
Performs the mutation on the database schema in the reverse
|
Drops a model's table.
|
||||||
direction - e.g. if this were CreateModel, it would in fact
|
|
||||||
drop the model's table.
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def state_forwards(self, app_label, state):
|
||||||
|
del state.models[app_label, self.name.lower()]
|
||||||
|
|
||||||
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = from_state.render()
|
||||||
|
schema_editor.delete_model(app_cache.get_model(app_label, self.name))
|
||||||
|
|
||||||
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
||||||
|
app_cache = to_state.render()
|
||||||
|
schema_editor.create_model(app_cache.get_model(app_label, self.name))
|
||||||
|
|
|
@ -21,7 +21,7 @@ class ProjectState(object):
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"Returns an exact copy of this ProjectState"
|
"Returns an exact copy of this ProjectState"
|
||||||
return ProjectState(
|
return ProjectState(
|
||||||
models = dict((k, v.copy()) for k, v in self.models.items())
|
models = dict((k, v.clone()) for k, v in self.models.items())
|
||||||
)
|
)
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
@ -49,12 +49,15 @@ class ModelState(object):
|
||||||
mutate this one and then render it into a Model as required.
|
mutate this one and then render it into a Model as required.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, app_label, name, fields=None, options=None, bases=None):
|
def __init__(self, app_label, name, fields, options=None, bases=None):
|
||||||
self.app_label = app_label
|
self.app_label = app_label
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fields = fields or []
|
self.fields = fields
|
||||||
self.options = options or {}
|
self.options = options or {}
|
||||||
self.bases = bases or (models.Model, )
|
self.bases = bases or (models.Model, )
|
||||||
|
# Sanity-check that fields is NOT a dict. It must be ordered.
|
||||||
|
if isinstance(self.fields, dict):
|
||||||
|
raise ValueError("ModelState.fields cannot be a dict - it must be a list of 2-tuples.")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_model(cls, model):
|
def from_model(cls, model):
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
from django.db import migrations
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
pass
|
|
||||||
|
operations = [
|
||||||
|
|
||||||
|
migrations.CreateModel(
|
||||||
|
"Author",
|
||||||
|
[
|
||||||
|
("id", models.AutoField(primary_key=True)),
|
||||||
|
("name", models.CharField(max_length=255)),
|
||||||
|
("slug", models.SlugField(null=True)),
|
||||||
|
("age", models.IntegerField(default=0)),
|
||||||
|
("silly_field", models.BooleanField()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
migrations.CreateModel(
|
||||||
|
"Tribble",
|
||||||
|
[
|
||||||
|
("id", models.AutoField(primary_key=True)),
|
||||||
|
("fluffy", models.BooleanField(default=True)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
]
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
from django.db import migrations
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [("migrations", "0001_initial")]
|
dependencies = [("migrations", "0001_initial")]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
|
||||||
|
migrations.DeleteModel("Tribble"),
|
||||||
|
|
||||||
|
migrations.RemoveField("Author", "silly_field"),
|
||||||
|
|
||||||
|
migrations.AddField("Author", "important", models.BooleanField()),
|
||||||
|
|
||||||
|
migrations.CreateModel(
|
||||||
|
"Book",
|
||||||
|
[
|
||||||
|
("id", models.AutoField(primary_key=True)),
|
||||||
|
("author", models.ForeignKey("migrations.Author", null=True)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
]
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
from django.test import TransactionTestCase, TestCase
|
from django.test import TestCase
|
||||||
from django.db import connection
|
|
||||||
from django.db.migrations.graph import MigrationGraph, CircularDependencyError
|
from django.db.migrations.graph import MigrationGraph, CircularDependencyError
|
||||||
from django.db.migrations.loader import MigrationLoader
|
|
||||||
from django.db.migrations.recorder import MigrationRecorder
|
|
||||||
|
|
||||||
|
|
||||||
class GraphTests(TransactionTestCase):
|
class GraphTests(TestCase):
|
||||||
"""
|
"""
|
||||||
Tests the digraph structure.
|
Tests the digraph structure.
|
||||||
"""
|
"""
|
||||||
|
@ -117,20 +114,3 @@ class GraphTests(TransactionTestCase):
|
||||||
CircularDependencyError,
|
CircularDependencyError,
|
||||||
graph.forwards_plan, ("app_a", "0003"),
|
graph.forwards_plan, ("app_a", "0003"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class LoaderTests(TransactionTestCase):
|
|
||||||
"""
|
|
||||||
Tests the disk and database loader.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def test_load(self):
|
|
||||||
"""
|
|
||||||
Makes sure the loader can load the migrations for the test apps.
|
|
||||||
"""
|
|
||||||
migration_loader = MigrationLoader(connection)
|
|
||||||
graph = migration_loader.build_graph()
|
|
||||||
self.assertEqual(
|
|
||||||
graph.forwards_plan(("migrations", "0002_second")),
|
|
||||||
[("migrations", "0001_initial"), ("migrations", "0002_second")],
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase, TransactionTestCase
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
from django.db.migrations.loader import MigrationLoader
|
||||||
from django.db.migrations.recorder import MigrationRecorder
|
from django.db.migrations.recorder import MigrationRecorder
|
||||||
|
|
||||||
|
|
||||||
class RecorderTests(TestCase):
|
class RecorderTests(TestCase):
|
||||||
"""
|
"""
|
||||||
Tests the disk and database loader.
|
Tests recording migrations as applied or not.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def test_apply(self):
|
def test_apply(self):
|
||||||
|
@ -27,3 +28,37 @@ class RecorderTests(TestCase):
|
||||||
recorder.applied_migrations(),
|
recorder.applied_migrations(),
|
||||||
set(),
|
set(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LoaderTests(TransactionTestCase):
|
||||||
|
"""
|
||||||
|
Tests the disk and database loader, and running through migrations
|
||||||
|
in memory.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_load(self):
|
||||||
|
"""
|
||||||
|
Makes sure the loader can load the migrations for the test apps,
|
||||||
|
and then render them out to a new AppCache.
|
||||||
|
"""
|
||||||
|
# Load and test the plan
|
||||||
|
migration_loader = MigrationLoader(connection)
|
||||||
|
self.assertEqual(
|
||||||
|
migration_loader.graph.forwards_plan(("migrations", "0002_second")),
|
||||||
|
[("migrations", "0001_initial"), ("migrations", "0002_second")],
|
||||||
|
)
|
||||||
|
# Now render it out!
|
||||||
|
project_state = migration_loader.graph.project_state(("migrations", "0002_second"))
|
||||||
|
self.assertEqual(len(project_state.models), 2)
|
||||||
|
|
||||||
|
author_state = project_state.models["migrations", "author"]
|
||||||
|
self.assertEqual(
|
||||||
|
[x for x, y in author_state.fields],
|
||||||
|
["id", "name", "slug", "age", "important"]
|
||||||
|
)
|
||||||
|
|
||||||
|
book_state = project_state.models["migrations", "book"]
|
||||||
|
self.assertEqual(
|
||||||
|
[x for x, y in book_state.fields],
|
||||||
|
["id", "author"]
|
||||||
|
)
|
||||||
|
|
|
@ -132,7 +132,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
else:
|
else:
|
||||||
self.fail("No FK constraint for author_id found")
|
self.fail("No FK constraint for author_id found")
|
||||||
|
|
||||||
def test_create_field(self):
|
def test_add_field(self):
|
||||||
"""
|
"""
|
||||||
Tests adding fields to models
|
Tests adding fields to models
|
||||||
"""
|
"""
|
||||||
|
@ -146,7 +146,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
new_field = IntegerField(null=True)
|
new_field = IntegerField(null=True)
|
||||||
new_field.set_attributes_from_name("age")
|
new_field.set_attributes_from_name("age")
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.create_field(
|
editor.add_field(
|
||||||
Author,
|
Author,
|
||||||
new_field,
|
new_field,
|
||||||
)
|
)
|
||||||
|
@ -251,7 +251,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
connection.rollback()
|
connection.rollback()
|
||||||
# Add the field
|
# Add the field
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.create_field(
|
editor.add_field(
|
||||||
Author,
|
Author,
|
||||||
new_field,
|
new_field,
|
||||||
)
|
)
|
||||||
|
@ -260,7 +260,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
self.assertEqual(columns['tag_id'][0], "IntegerField")
|
self.assertEqual(columns['tag_id'][0], "IntegerField")
|
||||||
# Remove the M2M table again
|
# Remove the M2M table again
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.delete_field(
|
editor.remove_field(
|
||||||
Author,
|
Author,
|
||||||
new_field,
|
new_field,
|
||||||
)
|
)
|
||||||
|
@ -530,7 +530,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
)
|
)
|
||||||
# Add a unique column, verify that creates an implicit index
|
# Add a unique column, verify that creates an implicit index
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.create_field(
|
editor.add_field(
|
||||||
Book,
|
Book,
|
||||||
BookWithSlug._meta.get_field_by_name("slug")[0],
|
BookWithSlug._meta.get_field_by_name("slug")[0],
|
||||||
)
|
)
|
||||||
|
@ -568,7 +568,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
new_field = SlugField(primary_key=True)
|
new_field = SlugField(primary_key=True)
|
||||||
new_field.set_attributes_from_name("slug")
|
new_field.set_attributes_from_name("slug")
|
||||||
with connection.schema_editor() as editor:
|
with connection.schema_editor() as editor:
|
||||||
editor.delete_field(Tag, Tag._meta.get_field_by_name("id")[0])
|
editor.remove_field(Tag, Tag._meta.get_field_by_name("id")[0])
|
||||||
editor.alter_field(
|
editor.alter_field(
|
||||||
Tag,
|
Tag,
|
||||||
Tag._meta.get_field_by_name("slug")[0],
|
Tag._meta.get_field_by_name("slug")[0],
|
||||||
|
|
Loading…
Reference in New Issue