1. from django import forms
    
  2. from django.core.exceptions import NON_FIELD_ERRORS
    
  3. from django.test import TestCase
    
  4. from django.utils.functional import lazy
    
  5. 
    
  6. from . import ValidationAssertions
    
  7. from .models import (
    
  8.     Article,
    
  9.     Author,
    
  10.     GenericIPAddressTestModel,
    
  11.     GenericIPAddrUnpackUniqueTest,
    
  12.     ModelToValidate,
    
  13. )
    
  14. 
    
  15. 
    
  16. class BaseModelValidationTests(ValidationAssertions, TestCase):
    
  17.     def test_missing_required_field_raises_error(self):
    
  18.         mtv = ModelToValidate(f_with_custom_validator=42)
    
  19.         self.assertFailsValidation(mtv.full_clean, ["name", "number"])
    
  20. 
    
  21.     def test_with_correct_value_model_validates(self):
    
  22.         mtv = ModelToValidate(number=10, name="Some Name")
    
  23.         self.assertIsNone(mtv.full_clean())
    
  24. 
    
  25.     def test_custom_validate_method(self):
    
  26.         mtv = ModelToValidate(number=11)
    
  27.         self.assertFailsValidation(mtv.full_clean, [NON_FIELD_ERRORS, "name"])
    
  28. 
    
  29.     def test_wrong_FK_value_raises_error(self):
    
  30.         mtv = ModelToValidate(number=10, name="Some Name", parent_id=3)
    
  31.         self.assertFieldFailsValidationWithMessage(
    
  32.             mtv.full_clean,
    
  33.             "parent",
    
  34.             ["model to validate instance with id %r does not exist." % mtv.parent_id],
    
  35.         )
    
  36.         mtv = ModelToValidate(number=10, name="Some Name", ufm_id="Some Name")
    
  37.         self.assertFieldFailsValidationWithMessage(
    
  38.             mtv.full_clean,
    
  39.             "ufm",
    
  40.             [
    
  41.                 "unique fields model instance with unique_charfield %r does not exist."
    
  42.                 % mtv.name
    
  43.             ],
    
  44.         )
    
  45. 
    
  46.     def test_correct_FK_value_validates(self):
    
  47.         parent = ModelToValidate.objects.create(number=10, name="Some Name")
    
  48.         mtv = ModelToValidate(number=10, name="Some Name", parent_id=parent.pk)
    
  49.         self.assertIsNone(mtv.full_clean())
    
  50. 
    
  51.     def test_limited_FK_raises_error(self):
    
  52.         # The limit_choices_to on the parent field says that a parent object's
    
  53.         # number attribute must be 10, so this should fail validation.
    
  54.         parent = ModelToValidate.objects.create(number=11, name="Other Name")
    
  55.         mtv = ModelToValidate(number=10, name="Some Name", parent_id=parent.pk)
    
  56.         self.assertFailsValidation(mtv.full_clean, ["parent"])
    
  57. 
    
  58.     def test_FK_validates_using_base_manager(self):
    
  59.         # Archived articles are not available through the default manager, only
    
  60.         # the base manager.
    
  61.         author = Author.objects.create(name="Randy", archived=True)
    
  62.         article = Article(title="My Article", author=author)
    
  63.         self.assertIsNone(article.full_clean())
    
  64. 
    
  65.     def test_wrong_email_value_raises_error(self):
    
  66.         mtv = ModelToValidate(number=10, name="Some Name", email="not-an-email")
    
  67.         self.assertFailsValidation(mtv.full_clean, ["email"])
    
  68. 
    
  69.     def test_correct_email_value_passes(self):
    
  70.         mtv = ModelToValidate(number=10, name="Some Name", email="[email protected]")
    
  71.         self.assertIsNone(mtv.full_clean())
    
  72. 
    
  73.     def test_wrong_url_value_raises_error(self):
    
  74.         mtv = ModelToValidate(number=10, name="Some Name", url="not a url")
    
  75.         self.assertFieldFailsValidationWithMessage(
    
  76.             mtv.full_clean, "url", ["Enter a valid URL."]
    
  77.         )
    
  78. 
    
  79.     def test_text_greater_that_charfields_max_length_raises_errors(self):
    
  80.         mtv = ModelToValidate(number=10, name="Some Name" * 100)
    
  81.         self.assertFailsValidation(mtv.full_clean, ["name"])
    
  82. 
    
  83.     def test_malformed_slug_raises_error(self):
    
  84.         mtv = ModelToValidate(number=10, name="Some Name", slug="##invalid##")
    
  85.         self.assertFailsValidation(mtv.full_clean, ["slug"])
    
  86. 
    
  87.     def test_full_clean_does_not_mutate_exclude(self):
    
  88.         mtv = ModelToValidate(f_with_custom_validator=42)
    
  89.         exclude = ["number"]
    
  90.         self.assertFailsValidation(mtv.full_clean, ["name"], exclude=exclude)
    
  91.         self.assertEqual(len(exclude), 1)
    
  92.         self.assertEqual(exclude[0], "number")
    
  93. 
    
  94. 
    
  95. class ArticleForm(forms.ModelForm):
    
  96.     class Meta:
    
  97.         model = Article
    
  98.         exclude = ["author"]
    
  99. 
    
  100. 
    
  101. class ModelFormsTests(TestCase):
    
  102.     @classmethod
    
  103.     def setUpTestData(cls):
    
  104.         cls.author = Author.objects.create(name="Joseph Kocherhans")
    
  105. 
    
  106.     def test_partial_validation(self):
    
  107.         # Make sure the "commit=False and set field values later" idiom still
    
  108.         # works with model validation.
    
  109.         data = {
    
  110.             "title": "The state of model validation",
    
  111.             "pub_date": "2010-1-10 14:49:00",
    
  112.         }
    
  113.         form = ArticleForm(data)
    
  114.         self.assertEqual(list(form.errors), [])
    
  115.         article = form.save(commit=False)
    
  116.         article.author = self.author
    
  117.         article.save()
    
  118. 
    
  119.     def test_validation_with_empty_blank_field(self):
    
  120.         # Since a value for pub_date wasn't provided and the field is
    
  121.         # blank=True, model-validation should pass.
    
  122.         # Also, Article.clean() should be run, so pub_date will be filled after
    
  123.         # validation, so the form should save cleanly even though pub_date is
    
  124.         # not allowed to be null.
    
  125.         data = {
    
  126.             "title": "The state of model validation",
    
  127.         }
    
  128.         article = Article(author_id=self.author.id)
    
  129.         form = ArticleForm(data, instance=article)
    
  130.         self.assertEqual(list(form.errors), [])
    
  131.         self.assertIsNotNone(form.instance.pub_date)
    
  132.         article = form.save()
    
  133. 
    
  134.     def test_validation_with_invalid_blank_field(self):
    
  135.         # Even though pub_date is set to blank=True, an invalid value was
    
  136.         # provided, so it should fail validation.
    
  137.         data = {"title": "The state of model validation", "pub_date": "never"}
    
  138.         article = Article(author_id=self.author.id)
    
  139.         form = ArticleForm(data, instance=article)
    
  140.         self.assertEqual(list(form.errors), ["pub_date"])
    
  141. 
    
  142. 
    
  143. class GenericIPAddressFieldTests(ValidationAssertions, TestCase):
    
  144.     def test_correct_generic_ip_passes(self):
    
  145.         giptm = GenericIPAddressTestModel(generic_ip="1.2.3.4")
    
  146.         self.assertIsNone(giptm.full_clean())
    
  147.         giptm = GenericIPAddressTestModel(generic_ip=" 1.2.3.4 ")
    
  148.         self.assertIsNone(giptm.full_clean())
    
  149.         giptm = GenericIPAddressTestModel(generic_ip="1.2.3.4\n")
    
  150.         self.assertIsNone(giptm.full_clean())
    
  151.         giptm = GenericIPAddressTestModel(generic_ip="2001::2")
    
  152.         self.assertIsNone(giptm.full_clean())
    
  153. 
    
  154.     def test_invalid_generic_ip_raises_error(self):
    
  155.         giptm = GenericIPAddressTestModel(generic_ip="294.4.2.1")
    
  156.         self.assertFailsValidation(giptm.full_clean, ["generic_ip"])
    
  157.         giptm = GenericIPAddressTestModel(generic_ip="1:2")
    
  158.         self.assertFailsValidation(giptm.full_clean, ["generic_ip"])
    
  159.         giptm = GenericIPAddressTestModel(generic_ip=1)
    
  160.         self.assertFailsValidation(giptm.full_clean, ["generic_ip"])
    
  161.         giptm = GenericIPAddressTestModel(generic_ip=lazy(lambda: 1, int))
    
  162.         self.assertFailsValidation(giptm.full_clean, ["generic_ip"])
    
  163. 
    
  164.     def test_correct_v4_ip_passes(self):
    
  165.         giptm = GenericIPAddressTestModel(v4_ip="1.2.3.4")
    
  166.         self.assertIsNone(giptm.full_clean())
    
  167. 
    
  168.     def test_invalid_v4_ip_raises_error(self):
    
  169.         giptm = GenericIPAddressTestModel(v4_ip="294.4.2.1")
    
  170.         self.assertFailsValidation(giptm.full_clean, ["v4_ip"])
    
  171.         giptm = GenericIPAddressTestModel(v4_ip="2001::2")
    
  172.         self.assertFailsValidation(giptm.full_clean, ["v4_ip"])
    
  173. 
    
  174.     def test_correct_v6_ip_passes(self):
    
  175.         giptm = GenericIPAddressTestModel(v6_ip="2001::2")
    
  176.         self.assertIsNone(giptm.full_clean())
    
  177. 
    
  178.     def test_invalid_v6_ip_raises_error(self):
    
  179.         giptm = GenericIPAddressTestModel(v6_ip="1.2.3.4")
    
  180.         self.assertFailsValidation(giptm.full_clean, ["v6_ip"])
    
  181.         giptm = GenericIPAddressTestModel(v6_ip="1:2")
    
  182.         self.assertFailsValidation(giptm.full_clean, ["v6_ip"])
    
  183. 
    
  184.     def test_v6_uniqueness_detection(self):
    
  185.         # These two addresses are the same with different syntax
    
  186.         giptm = GenericIPAddressTestModel(generic_ip="2001::1:0:0:0:0:2")
    
  187.         giptm.save()
    
  188.         giptm = GenericIPAddressTestModel(generic_ip="2001:0:1:2")
    
  189.         self.assertFailsValidation(giptm.full_clean, ["generic_ip"])
    
  190. 
    
  191.     def test_v4_unpack_uniqueness_detection(self):
    
  192.         # These two are different, because we are not doing IPv4 unpacking
    
  193.         giptm = GenericIPAddressTestModel(generic_ip="::ffff:10.10.10.10")
    
  194.         giptm.save()
    
  195.         giptm = GenericIPAddressTestModel(generic_ip="10.10.10.10")
    
  196.         self.assertIsNone(giptm.full_clean())
    
  197. 
    
  198.         # These two are the same, because we are doing IPv4 unpacking
    
  199.         giptm = GenericIPAddrUnpackUniqueTest(generic_v4unpack_ip="::ffff:18.52.18.52")
    
  200.         giptm.save()
    
  201.         giptm = GenericIPAddrUnpackUniqueTest(generic_v4unpack_ip="18.52.18.52")
    
  202.         self.assertFailsValidation(giptm.full_clean, ["generic_v4unpack_ip"])
    
  203. 
    
  204.     def test_empty_generic_ip_passes(self):
    
  205.         giptm = GenericIPAddressTestModel(generic_ip="")
    
  206.         self.assertIsNone(giptm.full_clean())
    
  207.         giptm = GenericIPAddressTestModel(generic_ip=None)
    
  208.         self.assertIsNone(giptm.full_clean())