ModelState now freezes options and bases
This commit is contained in:
parent
d58c98d73c
commit
264f8650e3
|
@ -1,5 +1,6 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.loading import BaseAppCache
|
from django.db.models.loading import BaseAppCache
|
||||||
|
from django.db.models.options import DEFAULT_NAMES
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_by_path
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,13 +67,21 @@ class ModelState(object):
|
||||||
name, path, args, kwargs = field.deconstruct()
|
name, path, args, kwargs = field.deconstruct()
|
||||||
field_class = import_by_path(path)
|
field_class = import_by_path(path)
|
||||||
fields.append((name, field_class(*args, **kwargs)))
|
fields.append((name, field_class(*args, **kwargs)))
|
||||||
|
# Extract the options
|
||||||
|
options = {}
|
||||||
|
for name in DEFAULT_NAMES:
|
||||||
|
# Ignore some special options
|
||||||
|
if name in ["app_cache", "app_label"]:
|
||||||
|
continue
|
||||||
|
if name in model._meta.original_attrs:
|
||||||
|
options[name] = model._meta.original_attrs[name]
|
||||||
# Make our record
|
# Make our record
|
||||||
return cls(
|
return cls(
|
||||||
model._meta.app_label,
|
model._meta.app_label,
|
||||||
model._meta.object_name,
|
model._meta.object_name,
|
||||||
fields,
|
fields,
|
||||||
{},
|
options,
|
||||||
None,
|
model.__bases__,
|
||||||
)
|
)
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
|
|
|
@ -85,6 +85,10 @@ class Options(object):
|
||||||
self.model_name = self.object_name.lower()
|
self.model_name = self.object_name.lower()
|
||||||
self.verbose_name = get_verbose_name(self.object_name)
|
self.verbose_name = get_verbose_name(self.object_name)
|
||||||
|
|
||||||
|
# Store the original user-defined values for each option,
|
||||||
|
# for use when serializing the model definition
|
||||||
|
self.original_attrs = {}
|
||||||
|
|
||||||
# Next, apply any overridden values from 'class Meta'.
|
# Next, apply any overridden values from 'class Meta'.
|
||||||
if self.meta:
|
if self.meta:
|
||||||
meta_attrs = self.meta.__dict__.copy()
|
meta_attrs = self.meta.__dict__.copy()
|
||||||
|
@ -97,8 +101,10 @@ class Options(object):
|
||||||
for attr_name in DEFAULT_NAMES:
|
for attr_name in DEFAULT_NAMES:
|
||||||
if attr_name in meta_attrs:
|
if attr_name in meta_attrs:
|
||||||
setattr(self, attr_name, meta_attrs.pop(attr_name))
|
setattr(self, attr_name, meta_attrs.pop(attr_name))
|
||||||
|
self.original_attrs[attr_name] = getattr(self, attr_name)
|
||||||
elif hasattr(self.meta, attr_name):
|
elif hasattr(self.meta, attr_name):
|
||||||
setattr(self, attr_name, getattr(self.meta, attr_name))
|
setattr(self, attr_name, getattr(self.meta, attr_name))
|
||||||
|
self.original_attrs[attr_name] = getattr(self, attr_name)
|
||||||
|
|
||||||
# unique_together can be either a tuple of tuples, or a single
|
# unique_together can be either a tuple of tuples, or a single
|
||||||
# tuple of two strings. Normalize it to a tuple of tuples, so that
|
# tuple of two strings. Normalize it to a tuple of tuples, so that
|
||||||
|
|
|
@ -23,6 +23,7 @@ class StateTests(TestCase):
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "migrations"
|
app_label = "migrations"
|
||||||
app_cache = new_app_cache
|
app_cache = new_app_cache
|
||||||
|
unique_together = ["name", "bio"]
|
||||||
|
|
||||||
class Book(models.Model):
|
class Book(models.Model):
|
||||||
title = models.CharField(max_length=1000)
|
title = models.CharField(max_length=1000)
|
||||||
|
@ -30,6 +31,8 @@ class StateTests(TestCase):
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "migrations"
|
app_label = "migrations"
|
||||||
app_cache = new_app_cache
|
app_cache = new_app_cache
|
||||||
|
verbose_name = "tome"
|
||||||
|
db_table = "test_tome"
|
||||||
|
|
||||||
project_state = ProjectState.from_app_cache(new_app_cache)
|
project_state = ProjectState.from_app_cache(new_app_cache)
|
||||||
author_state = project_state.models['migrations', 'author']
|
author_state = project_state.models['migrations', 'author']
|
||||||
|
@ -41,6 +44,7 @@ class StateTests(TestCase):
|
||||||
self.assertEqual(author_state.fields[1][1].max_length, 255)
|
self.assertEqual(author_state.fields[1][1].max_length, 255)
|
||||||
self.assertEqual(author_state.fields[2][1].null, False)
|
self.assertEqual(author_state.fields[2][1].null, False)
|
||||||
self.assertEqual(author_state.fields[3][1].null, True)
|
self.assertEqual(author_state.fields[3][1].null, True)
|
||||||
|
self.assertEqual(author_state.options, {"unique_together": ["name", "bio"]})
|
||||||
self.assertEqual(author_state.bases, (models.Model, ))
|
self.assertEqual(author_state.bases, (models.Model, ))
|
||||||
|
|
||||||
self.assertEqual(book_state.app_label, "migrations")
|
self.assertEqual(book_state.app_label, "migrations")
|
||||||
|
@ -48,6 +52,7 @@ class StateTests(TestCase):
|
||||||
self.assertEqual([x for x, y in book_state.fields], ["id", "title", "author"])
|
self.assertEqual([x for x, y in book_state.fields], ["id", "title", "author"])
|
||||||
self.assertEqual(book_state.fields[1][1].max_length, 1000)
|
self.assertEqual(book_state.fields[1][1].max_length, 1000)
|
||||||
self.assertEqual(book_state.fields[2][1].null, False)
|
self.assertEqual(book_state.fields[2][1].null, False)
|
||||||
|
self.assertEqual(book_state.options, {"verbose_name": "tome", "db_table": "test_tome"})
|
||||||
self.assertEqual(book_state.bases, (models.Model, ))
|
self.assertEqual(book_state.bases, (models.Model, ))
|
||||||
|
|
||||||
def test_render(self):
|
def test_render(self):
|
||||||
|
|
Loading…
Reference in New Issue