ModelState now freezes options and bases

This commit is contained in:
Andrew Godwin 2013-05-19 12:35:17 +02:00
parent d58c98d73c
commit 264f8650e3
3 changed files with 22 additions and 2 deletions

View File

@ -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):

View File

@ -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

View File

@ -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):