Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Ported over Field.deconstruct() from my schema alteration branch.

This is to help other ongoing branches which would benefit from
this functionality.
  • Loading branch information...
commit 48dd1e63bbb93479666208535a56f8c7c4aeab3a 1 parent 8809da6
@andrewgodwin andrewgodwin authored
View
188 django/db/models/fields/__init__.py
@@ -99,7 +99,8 @@ def __init__(self, verbose_name=None, name=None, primary_key=False,
db_tablespace=None, auto_created=False, validators=[],
error_messages=None):
self.name = name
- self.verbose_name = verbose_name
+ self.verbose_name = verbose_name # May be set by set_attributes_from_name
+ self._verbose_name = verbose_name # Store original for deconstruction
self.primary_key = primary_key
self.max_length, self._unique = max_length, unique
self.blank, self.null = blank, null
@@ -128,14 +129,99 @@ def __init__(self, verbose_name=None, name=None, primary_key=False,
self.creation_counter = Field.creation_counter
Field.creation_counter += 1
+ self._validators = validators # Store for deconstruction later
self.validators = self.default_validators + validators
messages = {}
for c in reversed(self.__class__.__mro__):
messages.update(getattr(c, 'default_error_messages', {}))
messages.update(error_messages or {})
+ self._error_messages = error_messages # Store for deconstruction later
self.error_messages = messages
+ def deconstruct(self):
+ """
+ Returns enough information to recreate the field as a 4-tuple:
+
+ * The name of the field on the model, if contribute_to_class has been run
+ * The import path of the field, including the class: django.db.models.IntegerField
+ This should be the most portable version, so less specific may be better.
+ * A list of positional arguments
+ * A dict of keyword arguments
+
+ Note that the positional or keyword arguments must contain values of the
+ following types (including inner values of collection types):
+
+ * None, bool, str, unicode, int, long, float, complex, set, frozenset, list, tuple, dict
+ * UUID
+ * datetime.datetime (naive), datetime.date
+ * top-level classes, top-level functions - will be referenced by their full import path
+ * Storage instances - these have their own deconstruct() method
+
+ This is because the values here must be serialised into a text format
+ (possibly new Python code, possibly JSON) and these are the only types
+ with encoding handlers defined.
+
+ There's no need to return the exact way the field was instantiated this time,
+ just ensure that the resulting field is the same - prefer keyword arguments
+ over positional ones, and omit parameters with their default values.
+ """
+ # Short-form way of fetching all the default parameters
+ keywords = {}
+ possibles = {
+ "verbose_name": None,
+ "primary_key": False,
+ "max_length": None,
+ "unique": False,
+ "blank": False,
+ "null": False,
+ "db_index": False,
+ "default": NOT_PROVIDED,
+ "editable": True,
+ "serialize": True,
+ "unique_for_date": None,
+ "unique_for_month": None,
+ "unique_for_year": None,
+ "choices": [],
+ "help_text": '',
+ "db_column": None,
+ "db_tablespace": settings.DEFAULT_INDEX_TABLESPACE,
+ "auto_created": False,
+ "validators": [],
+ "error_messages": None,
+ }
+ attr_overrides = {
+ "unique": "_unique",
+ "choices": "_choices",
+ "error_messages": "_error_messages",
+ "validators": "_validators",
+ "verbose_name": "_verbose_name",
+ }
+ equals_comparison = set(["choices", "validators", "db_tablespace"])
+ for name, default in possibles.items():
+ value = getattr(self, attr_overrides.get(name, name))
+ if name in equals_comparison:
+ if value != default:
+ keywords[name] = value
+ else:
+ if value is not default:
+ keywords[name] = value
+ # Work out path - we shorten it for known Django core fields
+ path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
+ if path.startswith("django.db.models.fields.related"):
+ path = path.replace("django.db.models.fields.related", "django.db.models")
+ if path.startswith("django.db.models.fields.files"):
+ path = path.replace("django.db.models.fields.files", "django.db.models")
+ if path.startswith("django.db.models.fields"):
+ path = path.replace("django.db.models.fields", "django.db.models")
+ # Return basic info - other fields should override this.
+ return (
+ self.name,
+ path,
+ [],
+ keywords,
+ )
+
def __eq__(self, other):
# Needed for @total_ordering
if isinstance(other, Field):
@@ -566,6 +652,7 @@ def __repr__(self):
return '<%s: %s>' % (path, name)
return '<%s>' % path
+
class AutoField(Field):
description = _("Integer")
@@ -580,6 +667,12 @@ def __init__(self, *args, **kwargs):
kwargs['blank'] = True
Field.__init__(self, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(AutoField, self).deconstruct()
+ del kwargs['blank']
+ kwargs['primary_key'] = True
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "AutoField"
@@ -630,6 +723,11 @@ def __init__(self, *args, **kwargs):
kwargs['blank'] = True
Field.__init__(self, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(BooleanField, self).deconstruct()
+ del kwargs['blank']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "BooleanField"
@@ -733,6 +831,18 @@ def __init__(self, verbose_name=None, name=None, auto_now=False,
kwargs['blank'] = True
Field.__init__(self, verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(DateField, self).deconstruct()
+ if self.auto_now:
+ kwargs['auto_now'] = True
+ del kwargs['editable']
+ del kwargs['blank']
+ if self.auto_now_add:
+ kwargs['auto_now_add'] = True
+ del kwargs['editable']
+ del kwargs['blank']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "DateField"
@@ -927,6 +1037,14 @@ def __init__(self, verbose_name=None, name=None, max_digits=None,
self.max_digits, self.decimal_places = max_digits, decimal_places
Field.__init__(self, verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(DecimalField, self).deconstruct()
+ if self.max_digits:
+ kwargs['max_digits'] = self.max_digits
+ if self.decimal_places:
+ kwargs['decimal_places'] = self.decimal_places
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "DecimalField"
@@ -989,6 +1107,12 @@ def __init__(self, *args, **kwargs):
kwargs['max_length'] = kwargs.get('max_length', 75)
CharField.__init__(self, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(EmailField, self).deconstruct()
+ # We do not exclude max_length if it matches default as we want to change
+ # the default in future.
+ return name, path, args, kwargs
+
def formfield(self, **kwargs):
# As with CharField, this will cause email validation to be performed
# twice.
@@ -1008,6 +1132,22 @@ def __init__(self, verbose_name=None, name=None, path='', match=None,
kwargs['max_length'] = kwargs.get('max_length', 100)
Field.__init__(self, verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(FilePathField, self).deconstruct()
+ if self.path != '':
+ kwargs['path'] = self.path
+ if self.match is not None:
+ kwargs['match'] = self.match
+ if self.recursive is not False:
+ kwargs['recursive'] = self.recursive
+ if self.allow_files is not True:
+ kwargs['allow_files'] = self.allow_files
+ if self.allow_folders is not False:
+ kwargs['allow_folders'] = self.allow_folders
+ if kwargs.get("max_length", None) == 100:
+ del kwargs["max_length"]
+ return name, path, args, kwargs
+
def formfield(self, **kwargs):
defaults = {
'path': self.path,
@@ -1115,6 +1255,11 @@ def __init__(self, *args, **kwargs):
kwargs['max_length'] = 15
Field.__init__(self, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(IPAddressField, self).deconstruct()
+ del kwargs['max_length']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "IPAddressField"
@@ -1131,12 +1276,23 @@ class GenericIPAddressField(Field):
def __init__(self, verbose_name=None, name=None, protocol='both',
unpack_ipv4=False, *args, **kwargs):
self.unpack_ipv4 = unpack_ipv4
+ self.protocol = protocol
self.default_validators, invalid_error_message = \
validators.ip_address_validators(protocol, unpack_ipv4)
self.default_error_messages['invalid'] = invalid_error_message
kwargs['max_length'] = 39
Field.__init__(self, verbose_name, name, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(GenericIPAddressField, self).deconstruct()
+ if self.unpack_ipv4 is not False:
+ kwargs['unpack_ipv4'] = self.unpack_ipv4
+ if self.protocol != "both":
+ kwargs['protocol'] = self.protocol
+ if kwargs.get("max_length", None) == 39:
+ del kwargs['max_length']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "GenericIPAddressField"
@@ -1177,6 +1333,12 @@ def __init__(self, *args, **kwargs):
kwargs['blank'] = True
Field.__init__(self, *args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(NullBooleanField, self).deconstruct()
+ del kwargs['null']
+ del kwargs['blank']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "NullBooleanField"
@@ -1254,6 +1416,16 @@ def __init__(self, *args, **kwargs):
kwargs['db_index'] = True
super(SlugField, self).__init__(*args, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(SlugField, self).deconstruct()
+ if kwargs.get("max_length", None) == 50:
+ del kwargs['max_length']
+ if self.db_index is False:
+ kwargs['db_index'] = False
+ else:
+ del kwargs['db_index']
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "SlugField"
@@ -1302,6 +1474,14 @@ def __init__(self, verbose_name=None, name=None, auto_now=False,
kwargs['blank'] = True
Field.__init__(self, verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(TimeField, self).deconstruct()
+ if self.auto_now is not False:
+ kwargs["auto_now"] = self.auto_now
+ if self.auto_now_add is not False:
+ kwargs["auto_now_add"] = self.auto_now_add
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "TimeField"
@@ -1367,6 +1547,12 @@ def __init__(self, verbose_name=None, name=None, **kwargs):
kwargs['max_length'] = kwargs.get('max_length', 200)
CharField.__init__(self, verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(URLField, self).deconstruct()
+ if kwargs.get("max_length", None) == 200:
+ del kwargs['max_length']
+ return name, path, args, kwargs
+
def formfield(self, **kwargs):
# As with CharField, this will cause URL validation to be performed
# twice.
View
19 django/db/models/fields/files.py
@@ -227,6 +227,17 @@ def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **k
kwargs['max_length'] = kwargs.get('max_length', 100)
super(FileField, self).__init__(verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(FileField, self).deconstruct()
+ if kwargs.get("max_length", None) != 100:
+ kwargs["max_length"] = 100
+ else:
+ del kwargs["max_length"]
+ kwargs['upload_to'] = self.upload_to
+ if self.storage is not default_storage:
+ kwargs['storage'] = self.storage
+ return name, path, args, kwargs
+
def get_internal_type(self):
return "FileField"
@@ -326,6 +337,14 @@ def __init__(self, verbose_name=None, name=None, width_field=None,
self.width_field, self.height_field = width_field, height_field
super(ImageField, self).__init__(verbose_name, name, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(ImageField, self).deconstruct()
+ if self.width_field:
+ kwargs['width_field'] = self.width_field
+ if self.height_field:
+ kwargs['height_field'] = self.height_field
+ return name, path, args, kwargs
+
def contribute_to_class(self, cls, name):
super(ImageField, self).contribute_to_class(cls, name)
# Attach update_dimension_fields so that dimension fields declared
View
42 django/db/models/fields/related.py
@@ -1151,6 +1151,27 @@ def __init__(self, to, to_field=None, rel_class=ManyToOneRel,
)
super(ForeignKey, self).__init__(to, ['self'], [to_field], **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(ForeignKey, self).deconstruct()
+ # Handle the simpler arguments
+ if self.db_index:
+ del kwargs['db_index']
+ else:
+ kwargs['db_index'] = False
+ if self.db_constraint is not True:
+ kwargs['db_constraint'] = self.db_constraint
+ if self.rel.on_delete is not CASCADE:
+ kwargs['on_delete'] = self.rel.on_delete
+ # Rel needs more work.
+ rel = self.rel
+ if self.rel.field_name:
+ kwargs['to_field'] = self.rel.field_name
+ if isinstance(self.rel.to, basestring):
+ kwargs['to'] = self.rel.to
+ else:
+ kwargs['to'] = "%s.%s" % (self.rel.to._meta.app_label, self.rel.to._meta.object_name)
+ return name, path, args, kwargs
+
@property
def related_field(self):
return self.foreign_related_fields[0]
@@ -1268,6 +1289,12 @@ def __init__(self, to, to_field=None, **kwargs):
kwargs['unique'] = True
super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(OneToOneField, self).deconstruct()
+ if "unique" in kwargs:
+ del kwargs['unique']
+ return name, path, args, kwargs
+
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(),
SingleRelatedObjectDescriptor(related))
@@ -1357,6 +1384,21 @@ def __init__(self, to, db_constraint=True, **kwargs):
super(ManyToManyField, self).__init__(**kwargs)
+ def deconstruct(self):
+ name, path, args, kwargs = super(ManyToManyField, self).deconstruct()
+ # Handle the simpler arguments
+ if self.rel.db_constraint is not True:
+ kwargs['db_constraint'] = self.db_constraint
+ if "help_text" in kwargs:
+ del kwargs['help_text']
+ # Rel needs more work.
+ rel = self.rel
+ if isinstance(self.rel.to, basestring):
+ kwargs['to'] = self.rel.to
+ else:
+ kwargs['to'] = "%s.%s" % (self.rel.to._meta.app_label, self.rel.to._meta.object_name)
+ return name, path, args, kwargs
+
def _get_path_info(self, direct=False):
"""
Called by both direct an indirect m2m traversal.
View
0  tests/field_deconstruction/__init__.py
No changes.
View
0  tests/field_deconstruction/models.py
No changes.
View
253 tests/field_deconstruction/tests.py
@@ -0,0 +1,253 @@
+from django.test import TestCase
+from django.db import models
+
+
+class FieldDeconstructionTests(TestCase):
+ """
+ Tests the deconstruct() method on all core fields.
+ """
+
+ def test_name(self):
+ """
+ Tests the outputting of the correct name if assigned one.
+ """
+ # First try using a "normal" field
+ field = models.CharField(max_length=65)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(name, None)
+ field.set_attributes_from_name("is_awesome_test")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(name, "is_awesome_test")
+ # Now try with a ForeignKey
+ field = models.ForeignKey("some_fake.ModelName")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(name, None)
+ field.set_attributes_from_name("author")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(name, "author")
+
+ def test_auto_field(self):
+ field = models.AutoField(primary_key=True)
+ field.set_attributes_from_name("id")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.AutoField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"primary_key": True})
+
+ def test_big_integer_field(self):
+ field = models.BigIntegerField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.BigIntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_boolean_field(self):
+ field = models.BooleanField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.BooleanField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+ field = models.BooleanField(default=True)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.BooleanField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"default": True})
+
+ def test_char_field(self):
+ field = models.CharField(max_length=65)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.CharField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_length": 65})
+ field = models.CharField(max_length=65, null=True, blank=True)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.CharField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_length": 65, "null": True, "blank": True})
+
+ def test_csi_field(self):
+ field = models.CommaSeparatedIntegerField(max_length=100)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.CommaSeparatedIntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_length": 100})
+
+ def test_date_field(self):
+ field = models.DateField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.DateField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+ field = models.DateField(auto_now=True)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.DateField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"auto_now": True})
+
+ def test_datetime_field(self):
+ field = models.DateTimeField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.DateTimeField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+ field = models.DateTimeField(auto_now_add=True)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.DateTimeField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"auto_now_add": True})
+
+ def test_decimal_field(self):
+ field = models.DecimalField(max_digits=5, decimal_places=2)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.DecimalField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 2})
+
+ def test_email_field(self):
+ field = models.EmailField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.EmailField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_length": 75})
+ field = models.EmailField(max_length=255)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.EmailField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"max_length": 255})
+
+ def test_file_field(self):
+ field = models.FileField(upload_to="foo/bar")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.FileField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"upload_to": "foo/bar"})
+
+ def test_file_path_field(self):
+ field = models.FilePathField(match=".*\.txt$")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.FilePathField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"match": ".*\.txt$"})
+ field = models.FilePathField(recursive=True, allow_folders=True)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.FilePathField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"recursive": True, "allow_folders": True})
+
+ def test_float_field(self):
+ field = models.FloatField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.FloatField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_foreign_key(self):
+ field = models.ForeignKey("auth.User")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.ForeignKey")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"to": "auth.User"})
+ field = models.ForeignKey("something.Else")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.ForeignKey")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"to": "something.Else"})
+ field = models.ForeignKey("auth.User", on_delete=models.SET_NULL)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.ForeignKey")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"to": "auth.User", "on_delete": models.SET_NULL})
+
+ def test_image_field(self):
+ field = models.ImageField(upload_to="foo/barness", width_field="width", height_field="height")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.ImageField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"upload_to": "foo/barness", "width_field": "width", "height_field": "height"})
+
+ def test_integer_field(self):
+ field = models.IntegerField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.IntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_ip_address_field(self):
+ field = models.IPAddressField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.IPAddressField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_generic_ip_address_field(self):
+ field = models.GenericIPAddressField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.GenericIPAddressField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+ field = models.GenericIPAddressField(protocol="IPv6")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.GenericIPAddressField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"protocol": "IPv6"})
+
+ def test_many_to_many_field(self):
+ field = models.ManyToManyField("auth.User")
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.ManyToManyField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"to": "auth.User"})
+
+ def test_null_boolean_field(self):
+ field = models.NullBooleanField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.NullBooleanField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_positive_integer_field(self):
+ field = models.PositiveIntegerField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.PositiveIntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_positive_small_integer_field(self):
+ field = models.PositiveSmallIntegerField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.PositiveSmallIntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_slug_field(self):
+ field = models.SlugField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.SlugField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+ field = models.SlugField(db_index=False)
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.SlugField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {"db_index": False})
+
+ def test_small_integer_field(self):
+ field = models.SmallIntegerField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.SmallIntegerField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_text_field(self):
+ field = models.TextField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.TextField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
+
+ def test_url_field(self):
+ field = models.URLField()
+ name, path, args, kwargs = field.deconstruct()
+ self.assertEqual(path, "django.db.models.URLField")
+ self.assertEqual(args, [])
+ self.assertEqual(kwargs, {})
Please sign in to comment.
Something went wrong with that request. Please try again.