In some cases, this could lead to migrations written with Python 2 being incompatible with Python 3. Thanks Tim Graham for the report and Loïc Bistuer for the advices. Backport of da9cf53cb from master.
334 lines
15 KiB
Python
334 lines
15 KiB
Python
import warnings
|
|
|
|
from django.db import models
|
|
from django.test import TestCase, override_settings
|
|
from django.utils import six
|
|
|
|
|
|
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.assertIsNone(name)
|
|
field.set_attributes_from_name("is_awesome_test")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(name, "is_awesome_test")
|
|
self.assertIsInstance(name, six.text_type)
|
|
# Now try with a ForeignKey
|
|
field = models.ForeignKey("some_fake.ModelName")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertIsNone(name)
|
|
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})
|
|
# Bug #21785
|
|
field = models.DateTimeField(auto_now=True, 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, "auto_now": 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_decimal_field_0_decimal_places(self):
|
|
"""
|
|
A DecimalField with decimal_places=0 should work (#22272).
|
|
"""
|
|
field = models.DecimalField(max_digits=5, decimal_places=0)
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.DecimalField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 0})
|
|
|
|
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"})
|
|
field = models.FileField(upload_to="foo/bar", max_length=200)
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.FileField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"upload_to": "foo/bar", "max_length": 200})
|
|
|
|
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, max_length=123)
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.FilePathField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"recursive": True, "allow_folders": True, "max_length": 123})
|
|
|
|
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):
|
|
# Test basic pointing
|
|
field = models.ForeignKey("auth.Permission")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.ForeignKey")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"to": "auth.Permission"})
|
|
self.assertFalse(hasattr(kwargs['to'], "setting_name"))
|
|
# Test swap detection for swappable model
|
|
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"})
|
|
self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
|
|
# Test nonexistent (for now) model
|
|
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"})
|
|
# Test on_delete
|
|
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})
|
|
|
|
@override_settings(AUTH_USER_MODEL="auth.Permission")
|
|
def test_foreign_key_swapped(self):
|
|
# It doesn't matter that we swapped out user for permission;
|
|
# there's no validation. We just want to check the setting stuff works.
|
|
field = models.ForeignKey("auth.Permission")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.ForeignKey")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"to": "auth.Permission"})
|
|
self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
|
|
|
|
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):
|
|
with warnings.catch_warnings(record=True):
|
|
warnings.simplefilter("always")
|
|
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):
|
|
# Test normal
|
|
field = models.ManyToManyField("auth.Permission")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.ManyToManyField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"to": "auth.Permission"})
|
|
self.assertFalse(hasattr(kwargs['to'], "setting_name"))
|
|
# Test swappable
|
|
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"})
|
|
self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
|
|
# Test through
|
|
field = models.ManyToManyField("auth.Permission", through="auth.Group")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.ManyToManyField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"to": "auth.Permission", "through": "auth.Group"})
|
|
|
|
@override_settings(AUTH_USER_MODEL="auth.Permission")
|
|
def test_many_to_many_field_swapped(self):
|
|
# It doesn't matter that we swapped out user for permission;
|
|
# there's no validation. We just want to check the setting stuff works.
|
|
field = models.ManyToManyField("auth.Permission")
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.ManyToManyField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"to": "auth.Permission"})
|
|
self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL")
|
|
|
|
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, max_length=231)
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.SlugField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"db_index": False, "max_length": 231})
|
|
|
|
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, {})
|
|
field = models.URLField(max_length=231)
|
|
name, path, args, kwargs = field.deconstruct()
|
|
self.assertEqual(path, "django.db.models.URLField")
|
|
self.assertEqual(args, [])
|
|
self.assertEqual(kwargs, {"max_length": 231})
|