1. from django.apps import apps
    
  2. from django.db import models
    
  3. from django.test import SimpleTestCase, override_settings
    
  4. from django.test.utils import isolate_lru_cache
    
  5. 
    
  6. 
    
  7. class FieldDeconstructionTests(SimpleTestCase):
    
  8.     """
    
  9.     Tests the deconstruct() method on all core fields.
    
  10.     """
    
  11. 
    
  12.     def test_name(self):
    
  13.         """
    
  14.         Tests the outputting of the correct name if assigned one.
    
  15.         """
    
  16.         # First try using a "normal" field
    
  17.         field = models.CharField(max_length=65)
    
  18.         name, path, args, kwargs = field.deconstruct()
    
  19.         self.assertIsNone(name)
    
  20.         field.set_attributes_from_name("is_awesome_test")
    
  21.         name, path, args, kwargs = field.deconstruct()
    
  22.         self.assertEqual(name, "is_awesome_test")
    
  23.         # Now try with a ForeignKey
    
  24.         field = models.ForeignKey("some_fake.ModelName", models.CASCADE)
    
  25.         name, path, args, kwargs = field.deconstruct()
    
  26.         self.assertIsNone(name)
    
  27.         field.set_attributes_from_name("author")
    
  28.         name, path, args, kwargs = field.deconstruct()
    
  29.         self.assertEqual(name, "author")
    
  30. 
    
  31.     def test_db_tablespace(self):
    
  32.         field = models.Field()
    
  33.         _, _, args, kwargs = field.deconstruct()
    
  34.         self.assertEqual(args, [])
    
  35.         self.assertEqual(kwargs, {})
    
  36.         # With a DEFAULT_DB_TABLESPACE.
    
  37.         with self.settings(DEFAULT_DB_TABLESPACE="foo"):
    
  38.             _, _, args, kwargs = field.deconstruct()
    
  39.         self.assertEqual(args, [])
    
  40.         self.assertEqual(kwargs, {})
    
  41.         # With a db_tablespace.
    
  42.         field = models.Field(db_tablespace="foo")
    
  43.         _, _, args, kwargs = field.deconstruct()
    
  44.         self.assertEqual(args, [])
    
  45.         self.assertEqual(kwargs, {"db_tablespace": "foo"})
    
  46.         # With a db_tablespace equal to DEFAULT_DB_TABLESPACE.
    
  47.         with self.settings(DEFAULT_DB_TABLESPACE="foo"):
    
  48.             _, _, args, kwargs = field.deconstruct()
    
  49.         self.assertEqual(args, [])
    
  50.         self.assertEqual(kwargs, {"db_tablespace": "foo"})
    
  51. 
    
  52.     def test_auto_field(self):
    
  53.         field = models.AutoField(primary_key=True)
    
  54.         field.set_attributes_from_name("id")
    
  55.         name, path, args, kwargs = field.deconstruct()
    
  56.         self.assertEqual(path, "django.db.models.AutoField")
    
  57.         self.assertEqual(args, [])
    
  58.         self.assertEqual(kwargs, {"primary_key": True})
    
  59. 
    
  60.     def test_big_integer_field(self):
    
  61.         field = models.BigIntegerField()
    
  62.         name, path, args, kwargs = field.deconstruct()
    
  63.         self.assertEqual(path, "django.db.models.BigIntegerField")
    
  64.         self.assertEqual(args, [])
    
  65.         self.assertEqual(kwargs, {})
    
  66. 
    
  67.     def test_boolean_field(self):
    
  68.         field = models.BooleanField()
    
  69.         name, path, args, kwargs = field.deconstruct()
    
  70.         self.assertEqual(path, "django.db.models.BooleanField")
    
  71.         self.assertEqual(args, [])
    
  72.         self.assertEqual(kwargs, {})
    
  73.         field = models.BooleanField(default=True)
    
  74.         name, path, args, kwargs = field.deconstruct()
    
  75.         self.assertEqual(path, "django.db.models.BooleanField")
    
  76.         self.assertEqual(args, [])
    
  77.         self.assertEqual(kwargs, {"default": True})
    
  78. 
    
  79.     def test_char_field(self):
    
  80.         field = models.CharField(max_length=65)
    
  81.         name, path, args, kwargs = field.deconstruct()
    
  82.         self.assertEqual(path, "django.db.models.CharField")
    
  83.         self.assertEqual(args, [])
    
  84.         self.assertEqual(kwargs, {"max_length": 65})
    
  85.         field = models.CharField(max_length=65, null=True, blank=True)
    
  86.         name, path, args, kwargs = field.deconstruct()
    
  87.         self.assertEqual(path, "django.db.models.CharField")
    
  88.         self.assertEqual(args, [])
    
  89.         self.assertEqual(kwargs, {"max_length": 65, "null": True, "blank": True})
    
  90. 
    
  91.     def test_char_field_choices(self):
    
  92.         field = models.CharField(max_length=1, choices=(("A", "One"), ("B", "Two")))
    
  93.         name, path, args, kwargs = field.deconstruct()
    
  94.         self.assertEqual(path, "django.db.models.CharField")
    
  95.         self.assertEqual(args, [])
    
  96.         self.assertEqual(
    
  97.             kwargs, {"choices": [("A", "One"), ("B", "Two")], "max_length": 1}
    
  98.         )
    
  99. 
    
  100.     def test_csi_field(self):
    
  101.         field = models.CommaSeparatedIntegerField(max_length=100)
    
  102.         name, path, args, kwargs = field.deconstruct()
    
  103.         self.assertEqual(path, "django.db.models.CommaSeparatedIntegerField")
    
  104.         self.assertEqual(args, [])
    
  105.         self.assertEqual(kwargs, {"max_length": 100})
    
  106. 
    
  107.     def test_date_field(self):
    
  108.         field = models.DateField()
    
  109.         name, path, args, kwargs = field.deconstruct()
    
  110.         self.assertEqual(path, "django.db.models.DateField")
    
  111.         self.assertEqual(args, [])
    
  112.         self.assertEqual(kwargs, {})
    
  113.         field = models.DateField(auto_now=True)
    
  114.         name, path, args, kwargs = field.deconstruct()
    
  115.         self.assertEqual(path, "django.db.models.DateField")
    
  116.         self.assertEqual(args, [])
    
  117.         self.assertEqual(kwargs, {"auto_now": True})
    
  118. 
    
  119.     def test_datetime_field(self):
    
  120.         field = models.DateTimeField()
    
  121.         name, path, args, kwargs = field.deconstruct()
    
  122.         self.assertEqual(path, "django.db.models.DateTimeField")
    
  123.         self.assertEqual(args, [])
    
  124.         self.assertEqual(kwargs, {})
    
  125.         field = models.DateTimeField(auto_now_add=True)
    
  126.         name, path, args, kwargs = field.deconstruct()
    
  127.         self.assertEqual(path, "django.db.models.DateTimeField")
    
  128.         self.assertEqual(args, [])
    
  129.         self.assertEqual(kwargs, {"auto_now_add": True})
    
  130.         # Bug #21785
    
  131.         field = models.DateTimeField(auto_now=True, auto_now_add=True)
    
  132.         name, path, args, kwargs = field.deconstruct()
    
  133.         self.assertEqual(path, "django.db.models.DateTimeField")
    
  134.         self.assertEqual(args, [])
    
  135.         self.assertEqual(kwargs, {"auto_now_add": True, "auto_now": True})
    
  136. 
    
  137.     def test_decimal_field(self):
    
  138.         field = models.DecimalField(max_digits=5, decimal_places=2)
    
  139.         name, path, args, kwargs = field.deconstruct()
    
  140.         self.assertEqual(path, "django.db.models.DecimalField")
    
  141.         self.assertEqual(args, [])
    
  142.         self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 2})
    
  143. 
    
  144.     def test_decimal_field_0_decimal_places(self):
    
  145.         """
    
  146.         A DecimalField with decimal_places=0 should work (#22272).
    
  147.         """
    
  148.         field = models.DecimalField(max_digits=5, decimal_places=0)
    
  149.         name, path, args, kwargs = field.deconstruct()
    
  150.         self.assertEqual(path, "django.db.models.DecimalField")
    
  151.         self.assertEqual(args, [])
    
  152.         self.assertEqual(kwargs, {"max_digits": 5, "decimal_places": 0})
    
  153. 
    
  154.     def test_email_field(self):
    
  155.         field = models.EmailField()
    
  156.         name, path, args, kwargs = field.deconstruct()
    
  157.         self.assertEqual(path, "django.db.models.EmailField")
    
  158.         self.assertEqual(args, [])
    
  159.         self.assertEqual(kwargs, {"max_length": 254})
    
  160.         field = models.EmailField(max_length=255)
    
  161.         name, path, args, kwargs = field.deconstruct()
    
  162.         self.assertEqual(path, "django.db.models.EmailField")
    
  163.         self.assertEqual(args, [])
    
  164.         self.assertEqual(kwargs, {"max_length": 255})
    
  165. 
    
  166.     def test_file_field(self):
    
  167.         field = models.FileField(upload_to="foo/bar")
    
  168.         name, path, args, kwargs = field.deconstruct()
    
  169.         self.assertEqual(path, "django.db.models.FileField")
    
  170.         self.assertEqual(args, [])
    
  171.         self.assertEqual(kwargs, {"upload_to": "foo/bar"})
    
  172.         # Test max_length
    
  173.         field = models.FileField(upload_to="foo/bar", max_length=200)
    
  174.         name, path, args, kwargs = field.deconstruct()
    
  175.         self.assertEqual(path, "django.db.models.FileField")
    
  176.         self.assertEqual(args, [])
    
  177.         self.assertEqual(kwargs, {"upload_to": "foo/bar", "max_length": 200})
    
  178. 
    
  179.     def test_file_path_field(self):
    
  180.         field = models.FilePathField(match=r".*\.txt$")
    
  181.         name, path, args, kwargs = field.deconstruct()
    
  182.         self.assertEqual(path, "django.db.models.FilePathField")
    
  183.         self.assertEqual(args, [])
    
  184.         self.assertEqual(kwargs, {"match": r".*\.txt$"})
    
  185.         field = models.FilePathField(recursive=True, allow_folders=True, max_length=123)
    
  186.         name, path, args, kwargs = field.deconstruct()
    
  187.         self.assertEqual(path, "django.db.models.FilePathField")
    
  188.         self.assertEqual(args, [])
    
  189.         self.assertEqual(
    
  190.             kwargs, {"recursive": True, "allow_folders": True, "max_length": 123}
    
  191.         )
    
  192. 
    
  193.     def test_float_field(self):
    
  194.         field = models.FloatField()
    
  195.         name, path, args, kwargs = field.deconstruct()
    
  196.         self.assertEqual(path, "django.db.models.FloatField")
    
  197.         self.assertEqual(args, [])
    
  198.         self.assertEqual(kwargs, {})
    
  199. 
    
  200.     def test_foreign_key(self):
    
  201.         # Test basic pointing
    
  202.         from django.contrib.auth.models import Permission
    
  203. 
    
  204.         field = models.ForeignKey("auth.Permission", models.CASCADE)
    
  205.         field.remote_field.model = Permission
    
  206.         field.remote_field.field_name = "id"
    
  207.         name, path, args, kwargs = field.deconstruct()
    
  208.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  209.         self.assertEqual(args, [])
    
  210.         self.assertEqual(kwargs, {"to": "auth.permission", "on_delete": models.CASCADE})
    
  211.         self.assertFalse(hasattr(kwargs["to"], "setting_name"))
    
  212.         # Test swap detection for swappable model
    
  213.         field = models.ForeignKey("auth.User", models.CASCADE)
    
  214.         name, path, args, kwargs = field.deconstruct()
    
  215.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  216.         self.assertEqual(args, [])
    
  217.         self.assertEqual(kwargs, {"to": "auth.user", "on_delete": models.CASCADE})
    
  218.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  219.         # Swap detection for lowercase swappable model.
    
  220.         field = models.ForeignKey("auth.user", models.CASCADE)
    
  221.         name, path, args, kwargs = field.deconstruct()
    
  222.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  223.         self.assertEqual(args, [])
    
  224.         self.assertEqual(kwargs, {"to": "auth.user", "on_delete": models.CASCADE})
    
  225.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  226.         # Test nonexistent (for now) model
    
  227.         field = models.ForeignKey("something.Else", models.CASCADE)
    
  228.         name, path, args, kwargs = field.deconstruct()
    
  229.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  230.         self.assertEqual(args, [])
    
  231.         self.assertEqual(kwargs, {"to": "something.else", "on_delete": models.CASCADE})
    
  232.         # Test on_delete
    
  233.         field = models.ForeignKey("auth.User", models.SET_NULL)
    
  234.         name, path, args, kwargs = field.deconstruct()
    
  235.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  236.         self.assertEqual(args, [])
    
  237.         self.assertEqual(kwargs, {"to": "auth.user", "on_delete": models.SET_NULL})
    
  238.         # Test to_field preservation
    
  239.         field = models.ForeignKey("auth.Permission", models.CASCADE, to_field="foobar")
    
  240.         name, path, args, kwargs = field.deconstruct()
    
  241.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  242.         self.assertEqual(args, [])
    
  243.         self.assertEqual(
    
  244.             kwargs,
    
  245.             {
    
  246.                 "to": "auth.permission",
    
  247.                 "to_field": "foobar",
    
  248.                 "on_delete": models.CASCADE,
    
  249.             },
    
  250.         )
    
  251.         # Test related_name preservation
    
  252.         field = models.ForeignKey(
    
  253.             "auth.Permission", models.CASCADE, related_name="foobar"
    
  254.         )
    
  255.         name, path, args, kwargs = field.deconstruct()
    
  256.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  257.         self.assertEqual(args, [])
    
  258.         self.assertEqual(
    
  259.             kwargs,
    
  260.             {
    
  261.                 "to": "auth.permission",
    
  262.                 "related_name": "foobar",
    
  263.                 "on_delete": models.CASCADE,
    
  264.             },
    
  265.         )
    
  266.         # Test related_query_name
    
  267.         field = models.ForeignKey(
    
  268.             "auth.Permission", models.CASCADE, related_query_name="foobar"
    
  269.         )
    
  270.         name, path, args, kwargs = field.deconstruct()
    
  271.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  272.         self.assertEqual(args, [])
    
  273.         self.assertEqual(
    
  274.             kwargs,
    
  275.             {
    
  276.                 "to": "auth.permission",
    
  277.                 "related_query_name": "foobar",
    
  278.                 "on_delete": models.CASCADE,
    
  279.             },
    
  280.         )
    
  281.         # Test limit_choices_to
    
  282.         field = models.ForeignKey(
    
  283.             "auth.Permission", models.CASCADE, limit_choices_to={"foo": "bar"}
    
  284.         )
    
  285.         name, path, args, kwargs = field.deconstruct()
    
  286.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  287.         self.assertEqual(args, [])
    
  288.         self.assertEqual(
    
  289.             kwargs,
    
  290.             {
    
  291.                 "to": "auth.permission",
    
  292.                 "limit_choices_to": {"foo": "bar"},
    
  293.                 "on_delete": models.CASCADE,
    
  294.             },
    
  295.         )
    
  296.         # Test unique
    
  297.         field = models.ForeignKey("auth.Permission", models.CASCADE, unique=True)
    
  298.         name, path, args, kwargs = field.deconstruct()
    
  299.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  300.         self.assertEqual(args, [])
    
  301.         self.assertEqual(
    
  302.             kwargs,
    
  303.             {"to": "auth.permission", "unique": True, "on_delete": models.CASCADE},
    
  304.         )
    
  305. 
    
  306.     @override_settings(AUTH_USER_MODEL="auth.Permission")
    
  307.     def test_foreign_key_swapped(self):
    
  308.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  309.             # It doesn't matter that we swapped out user for permission;
    
  310.             # there's no validation. We just want to check the setting stuff works.
    
  311.             field = models.ForeignKey("auth.Permission", models.CASCADE)
    
  312.             name, path, args, kwargs = field.deconstruct()
    
  313. 
    
  314.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  315.         self.assertEqual(args, [])
    
  316.         self.assertEqual(kwargs, {"to": "auth.permission", "on_delete": models.CASCADE})
    
  317.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  318. 
    
  319.         # Model names are case-insensitive.
    
  320.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  321.             # It doesn't matter that we swapped out user for permission;
    
  322.             # there's no validation. We just want to check the setting stuff
    
  323.             # works.
    
  324.             field = models.ForeignKey("auth.permission", models.CASCADE)
    
  325.             name, path, args, kwargs = field.deconstruct()
    
  326. 
    
  327.         self.assertEqual(path, "django.db.models.ForeignKey")
    
  328.         self.assertEqual(args, [])
    
  329.         self.assertEqual(kwargs, {"to": "auth.permission", "on_delete": models.CASCADE})
    
  330.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  331. 
    
  332.     def test_one_to_one(self):
    
  333.         # Test basic pointing
    
  334.         from django.contrib.auth.models import Permission
    
  335. 
    
  336.         field = models.OneToOneField("auth.Permission", models.CASCADE)
    
  337.         field.remote_field.model = Permission
    
  338.         field.remote_field.field_name = "id"
    
  339.         name, path, args, kwargs = field.deconstruct()
    
  340.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  341.         self.assertEqual(args, [])
    
  342.         self.assertEqual(kwargs, {"to": "auth.permission", "on_delete": models.CASCADE})
    
  343.         self.assertFalse(hasattr(kwargs["to"], "setting_name"))
    
  344.         # Test swap detection for swappable model
    
  345.         field = models.OneToOneField("auth.User", models.CASCADE)
    
  346.         name, path, args, kwargs = field.deconstruct()
    
  347.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  348.         self.assertEqual(args, [])
    
  349.         self.assertEqual(kwargs, {"to": "auth.user", "on_delete": models.CASCADE})
    
  350.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  351.         # Test nonexistent (for now) model
    
  352.         field = models.OneToOneField("something.Else", models.CASCADE)
    
  353.         name, path, args, kwargs = field.deconstruct()
    
  354.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  355.         self.assertEqual(args, [])
    
  356.         self.assertEqual(kwargs, {"to": "something.else", "on_delete": models.CASCADE})
    
  357.         # Test on_delete
    
  358.         field = models.OneToOneField("auth.User", models.SET_NULL)
    
  359.         name, path, args, kwargs = field.deconstruct()
    
  360.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  361.         self.assertEqual(args, [])
    
  362.         self.assertEqual(kwargs, {"to": "auth.user", "on_delete": models.SET_NULL})
    
  363.         # Test to_field
    
  364.         field = models.OneToOneField(
    
  365.             "auth.Permission", models.CASCADE, to_field="foobar"
    
  366.         )
    
  367.         name, path, args, kwargs = field.deconstruct()
    
  368.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  369.         self.assertEqual(args, [])
    
  370.         self.assertEqual(
    
  371.             kwargs,
    
  372.             {
    
  373.                 "to": "auth.permission",
    
  374.                 "to_field": "foobar",
    
  375.                 "on_delete": models.CASCADE,
    
  376.             },
    
  377.         )
    
  378.         # Test related_name
    
  379.         field = models.OneToOneField(
    
  380.             "auth.Permission", models.CASCADE, related_name="foobar"
    
  381.         )
    
  382.         name, path, args, kwargs = field.deconstruct()
    
  383.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  384.         self.assertEqual(args, [])
    
  385.         self.assertEqual(
    
  386.             kwargs,
    
  387.             {
    
  388.                 "to": "auth.permission",
    
  389.                 "related_name": "foobar",
    
  390.                 "on_delete": models.CASCADE,
    
  391.             },
    
  392.         )
    
  393.         # Test related_query_name
    
  394.         field = models.OneToOneField(
    
  395.             "auth.Permission", models.CASCADE, related_query_name="foobar"
    
  396.         )
    
  397.         name, path, args, kwargs = field.deconstruct()
    
  398.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  399.         self.assertEqual(args, [])
    
  400.         self.assertEqual(
    
  401.             kwargs,
    
  402.             {
    
  403.                 "to": "auth.permission",
    
  404.                 "related_query_name": "foobar",
    
  405.                 "on_delete": models.CASCADE,
    
  406.             },
    
  407.         )
    
  408.         # Test limit_choices_to
    
  409.         field = models.OneToOneField(
    
  410.             "auth.Permission", models.CASCADE, limit_choices_to={"foo": "bar"}
    
  411.         )
    
  412.         name, path, args, kwargs = field.deconstruct()
    
  413.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  414.         self.assertEqual(args, [])
    
  415.         self.assertEqual(
    
  416.             kwargs,
    
  417.             {
    
  418.                 "to": "auth.permission",
    
  419.                 "limit_choices_to": {"foo": "bar"},
    
  420.                 "on_delete": models.CASCADE,
    
  421.             },
    
  422.         )
    
  423.         # Test unique
    
  424.         field = models.OneToOneField("auth.Permission", models.CASCADE, unique=True)
    
  425.         name, path, args, kwargs = field.deconstruct()
    
  426.         self.assertEqual(path, "django.db.models.OneToOneField")
    
  427.         self.assertEqual(args, [])
    
  428.         self.assertEqual(kwargs, {"to": "auth.permission", "on_delete": models.CASCADE})
    
  429. 
    
  430.     def test_image_field(self):
    
  431.         field = models.ImageField(
    
  432.             upload_to="foo/barness", width_field="width", height_field="height"
    
  433.         )
    
  434.         name, path, args, kwargs = field.deconstruct()
    
  435.         self.assertEqual(path, "django.db.models.ImageField")
    
  436.         self.assertEqual(args, [])
    
  437.         self.assertEqual(
    
  438.             kwargs,
    
  439.             {
    
  440.                 "upload_to": "foo/barness",
    
  441.                 "width_field": "width",
    
  442.                 "height_field": "height",
    
  443.             },
    
  444.         )
    
  445. 
    
  446.     def test_integer_field(self):
    
  447.         field = models.IntegerField()
    
  448.         name, path, args, kwargs = field.deconstruct()
    
  449.         self.assertEqual(path, "django.db.models.IntegerField")
    
  450.         self.assertEqual(args, [])
    
  451.         self.assertEqual(kwargs, {})
    
  452. 
    
  453.     def test_ip_address_field(self):
    
  454.         field = models.IPAddressField()
    
  455.         name, path, args, kwargs = field.deconstruct()
    
  456.         self.assertEqual(path, "django.db.models.IPAddressField")
    
  457.         self.assertEqual(args, [])
    
  458.         self.assertEqual(kwargs, {})
    
  459. 
    
  460.     def test_generic_ip_address_field(self):
    
  461.         field = models.GenericIPAddressField()
    
  462.         name, path, args, kwargs = field.deconstruct()
    
  463.         self.assertEqual(path, "django.db.models.GenericIPAddressField")
    
  464.         self.assertEqual(args, [])
    
  465.         self.assertEqual(kwargs, {})
    
  466.         field = models.GenericIPAddressField(protocol="IPv6")
    
  467.         name, path, args, kwargs = field.deconstruct()
    
  468.         self.assertEqual(path, "django.db.models.GenericIPAddressField")
    
  469.         self.assertEqual(args, [])
    
  470.         self.assertEqual(kwargs, {"protocol": "IPv6"})
    
  471. 
    
  472.     def test_many_to_many_field(self):
    
  473.         # Test normal
    
  474.         field = models.ManyToManyField("auth.Permission")
    
  475.         name, path, args, kwargs = field.deconstruct()
    
  476.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  477.         self.assertEqual(args, [])
    
  478.         self.assertEqual(kwargs, {"to": "auth.permission"})
    
  479.         self.assertFalse(hasattr(kwargs["to"], "setting_name"))
    
  480.         # Test swappable
    
  481.         field = models.ManyToManyField("auth.User")
    
  482.         name, path, args, kwargs = field.deconstruct()
    
  483.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  484.         self.assertEqual(args, [])
    
  485.         self.assertEqual(kwargs, {"to": "auth.user"})
    
  486.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  487.         # Test through
    
  488.         field = models.ManyToManyField("auth.Permission", through="auth.Group")
    
  489.         name, path, args, kwargs = field.deconstruct()
    
  490.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  491.         self.assertEqual(args, [])
    
  492.         self.assertEqual(kwargs, {"to": "auth.permission", "through": "auth.Group"})
    
  493.         # Test custom db_table
    
  494.         field = models.ManyToManyField("auth.Permission", db_table="custom_table")
    
  495.         name, path, args, kwargs = field.deconstruct()
    
  496.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  497.         self.assertEqual(args, [])
    
  498.         self.assertEqual(kwargs, {"to": "auth.permission", "db_table": "custom_table"})
    
  499.         # Test related_name
    
  500.         field = models.ManyToManyField("auth.Permission", related_name="custom_table")
    
  501.         name, path, args, kwargs = field.deconstruct()
    
  502.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  503.         self.assertEqual(args, [])
    
  504.         self.assertEqual(
    
  505.             kwargs, {"to": "auth.permission", "related_name": "custom_table"}
    
  506.         )
    
  507.         # Test related_query_name
    
  508.         field = models.ManyToManyField("auth.Permission", related_query_name="foobar")
    
  509.         name, path, args, kwargs = field.deconstruct()
    
  510.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  511.         self.assertEqual(args, [])
    
  512.         self.assertEqual(
    
  513.             kwargs, {"to": "auth.permission", "related_query_name": "foobar"}
    
  514.         )
    
  515.         # Test limit_choices_to
    
  516.         field = models.ManyToManyField(
    
  517.             "auth.Permission", limit_choices_to={"foo": "bar"}
    
  518.         )
    
  519.         name, path, args, kwargs = field.deconstruct()
    
  520.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  521.         self.assertEqual(args, [])
    
  522.         self.assertEqual(
    
  523.             kwargs, {"to": "auth.permission", "limit_choices_to": {"foo": "bar"}}
    
  524.         )
    
  525. 
    
  526.     @override_settings(AUTH_USER_MODEL="auth.Permission")
    
  527.     def test_many_to_many_field_swapped(self):
    
  528.         with isolate_lru_cache(apps.get_swappable_settings_name):
    
  529.             # It doesn't matter that we swapped out user for permission;
    
  530.             # there's no validation. We just want to check the setting stuff works.
    
  531.             field = models.ManyToManyField("auth.Permission")
    
  532.             name, path, args, kwargs = field.deconstruct()
    
  533. 
    
  534.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  535.         self.assertEqual(args, [])
    
  536.         self.assertEqual(kwargs, {"to": "auth.permission"})
    
  537.         self.assertEqual(kwargs["to"].setting_name, "AUTH_USER_MODEL")
    
  538. 
    
  539.     def test_many_to_many_field_related_name(self):
    
  540.         class MyModel(models.Model):
    
  541.             flag = models.BooleanField(default=True)
    
  542.             m2m = models.ManyToManyField("self")
    
  543.             m2m_related_name = models.ManyToManyField(
    
  544.                 "self",
    
  545.                 related_query_name="custom_query_name",
    
  546.                 limit_choices_to={"flag": True},
    
  547.             )
    
  548. 
    
  549.         name, path, args, kwargs = MyModel.m2m.field.deconstruct()
    
  550.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  551.         self.assertEqual(args, [])
    
  552.         # deconstruct() should not include attributes which were not passed to
    
  553.         # the field during initialization.
    
  554.         self.assertEqual(kwargs, {"to": "field_deconstruction.mymodel"})
    
  555.         # Passed attributes.
    
  556.         name, path, args, kwargs = MyModel.m2m_related_name.field.deconstruct()
    
  557.         self.assertEqual(path, "django.db.models.ManyToManyField")
    
  558.         self.assertEqual(args, [])
    
  559.         self.assertEqual(
    
  560.             kwargs,
    
  561.             {
    
  562.                 "to": "field_deconstruction.mymodel",
    
  563.                 "related_query_name": "custom_query_name",
    
  564.                 "limit_choices_to": {"flag": True},
    
  565.             },
    
  566.         )
    
  567. 
    
  568.     def test_positive_integer_field(self):
    
  569.         field = models.PositiveIntegerField()
    
  570.         name, path, args, kwargs = field.deconstruct()
    
  571.         self.assertEqual(path, "django.db.models.PositiveIntegerField")
    
  572.         self.assertEqual(args, [])
    
  573.         self.assertEqual(kwargs, {})
    
  574. 
    
  575.     def test_positive_small_integer_field(self):
    
  576.         field = models.PositiveSmallIntegerField()
    
  577.         name, path, args, kwargs = field.deconstruct()
    
  578.         self.assertEqual(path, "django.db.models.PositiveSmallIntegerField")
    
  579.         self.assertEqual(args, [])
    
  580.         self.assertEqual(kwargs, {})
    
  581. 
    
  582.     def test_positive_big_integer_field(self):
    
  583.         field = models.PositiveBigIntegerField()
    
  584.         name, path, args, kwargs = field.deconstruct()
    
  585.         self.assertEqual(path, "django.db.models.PositiveBigIntegerField")
    
  586.         self.assertEqual(args, [])
    
  587.         self.assertEqual(kwargs, {})
    
  588. 
    
  589.     def test_slug_field(self):
    
  590.         field = models.SlugField()
    
  591.         name, path, args, kwargs = field.deconstruct()
    
  592.         self.assertEqual(path, "django.db.models.SlugField")
    
  593.         self.assertEqual(args, [])
    
  594.         self.assertEqual(kwargs, {})
    
  595.         field = models.SlugField(db_index=False, max_length=231)
    
  596.         name, path, args, kwargs = field.deconstruct()
    
  597.         self.assertEqual(path, "django.db.models.SlugField")
    
  598.         self.assertEqual(args, [])
    
  599.         self.assertEqual(kwargs, {"db_index": False, "max_length": 231})
    
  600. 
    
  601.     def test_small_integer_field(self):
    
  602.         field = models.SmallIntegerField()
    
  603.         name, path, args, kwargs = field.deconstruct()
    
  604.         self.assertEqual(path, "django.db.models.SmallIntegerField")
    
  605.         self.assertEqual(args, [])
    
  606.         self.assertEqual(kwargs, {})
    
  607. 
    
  608.     def test_text_field(self):
    
  609.         field = models.TextField()
    
  610.         name, path, args, kwargs = field.deconstruct()
    
  611.         self.assertEqual(path, "django.db.models.TextField")
    
  612.         self.assertEqual(args, [])
    
  613.         self.assertEqual(kwargs, {})
    
  614. 
    
  615.     def test_time_field(self):
    
  616.         field = models.TimeField()
    
  617.         name, path, args, kwargs = field.deconstruct()
    
  618.         self.assertEqual(path, "django.db.models.TimeField")
    
  619.         self.assertEqual(args, [])
    
  620.         self.assertEqual(kwargs, {})
    
  621. 
    
  622.         field = models.TimeField(auto_now=True)
    
  623.         name, path, args, kwargs = field.deconstruct()
    
  624.         self.assertEqual(args, [])
    
  625.         self.assertEqual(kwargs, {"auto_now": True})
    
  626. 
    
  627.         field = models.TimeField(auto_now_add=True)
    
  628.         name, path, args, kwargs = field.deconstruct()
    
  629.         self.assertEqual(args, [])
    
  630.         self.assertEqual(kwargs, {"auto_now_add": True})
    
  631. 
    
  632.     def test_url_field(self):
    
  633.         field = models.URLField()
    
  634.         name, path, args, kwargs = field.deconstruct()
    
  635.         self.assertEqual(path, "django.db.models.URLField")
    
  636.         self.assertEqual(args, [])
    
  637.         self.assertEqual(kwargs, {})
    
  638.         field = models.URLField(max_length=231)
    
  639.         name, path, args, kwargs = field.deconstruct()
    
  640.         self.assertEqual(path, "django.db.models.URLField")
    
  641.         self.assertEqual(args, [])
    
  642.         self.assertEqual(kwargs, {"max_length": 231})
    
  643. 
    
  644.     def test_binary_field(self):
    
  645.         field = models.BinaryField()
    
  646.         name, path, args, kwargs = field.deconstruct()
    
  647.         self.assertEqual(path, "django.db.models.BinaryField")
    
  648.         self.assertEqual(args, [])
    
  649.         self.assertEqual(kwargs, {})
    
  650.         field = models.BinaryField(editable=True)
    
  651.         name, path, args, kwargs = field.deconstruct()
    
  652.         self.assertEqual(args, [])
    
  653.         self.assertEqual(kwargs, {"editable": True})