diff --git a/django/forms/fields.py b/django/forms/fields.py
index 8b5fd2c..93047bb 100644
a
|
b
|
class URLField(CharField):
|
700 | 700 | # Rebuild the url_fields list, since the domain segment may now |
701 | 701 | # contain the path too. |
702 | 702 | url_fields = split_url(urlunsplit(url_fields)) |
703 | | if not url_fields[2]: |
| 703 | if url_fields[3] and not url_fields[2]: |
704 | 704 | # the path portion may need to be added before query params |
705 | 705 | url_fields[2] = '/' |
706 | 706 | value = urlunsplit(url_fields) |
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index 4d1890b..5dda7ea 100644
a
|
b
|
Miscellaneous
|
1103 | 1103 | * ``Widget.is_hidden`` is now a read-only property, getting its value by |
1104 | 1104 | introspecting the presence of ``input_type == 'hidden'``. |
1105 | 1105 | |
| 1106 | * ``URLField.to_python`` used to always add a trailing slash to pathless URLs. |
| 1107 | Now it only adds it if the URL contains a query part. |
| 1108 | |
1106 | 1109 | * :meth:`~django.db.models.query.QuerySet.select_related` now chains in the |
1107 | 1110 | same way as other similar calls like ``prefetch_related``. That is, |
1108 | 1111 | ``select_related('foo', 'bar')`` is equivalent to |
diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py
index 8cea26c..b7fd013 100644
a
|
b
|
class FieldsTests(SimpleTestCase):
|
737 | 737 | self.assertWidgetRendersTo(f, '<input type="url" name="f" id="id_f" />') |
738 | 738 | self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, '') |
739 | 739 | self.assertRaisesMessage(ValidationError, "'This field is required.'", f.clean, None) |
740 | | self.assertEqual('http://localhost/', f.clean('http://localhost')) |
741 | | self.assertEqual('http://example.com/', f.clean('http://example.com')) |
742 | | self.assertEqual('http://example.com./', f.clean('http://example.com.')) |
743 | | self.assertEqual('http://www.example.com/', f.clean('http://www.example.com')) |
| 740 | self.assertEqual('http://localhost', f.clean('http://localhost')) |
| 741 | self.assertEqual('http://example.com', f.clean('http://example.com')) |
| 742 | self.assertEqual('http://example.com.', f.clean('http://example.com.')) |
| 743 | self.assertEqual('http://www.example.com', f.clean('http://www.example.com')) |
744 | 744 | self.assertEqual('http://www.example.com:8000/test', f.clean('http://www.example.com:8000/test')) |
745 | | self.assertEqual('http://valid-with-hyphens.com/', f.clean('valid-with-hyphens.com')) |
746 | | self.assertEqual('http://subdomain.domain.com/', f.clean('subdomain.domain.com')) |
747 | | self.assertEqual('http://200.8.9.10/', f.clean('http://200.8.9.10')) |
| 745 | self.assertEqual('http://valid-with-hyphens.com', f.clean('valid-with-hyphens.com')) |
| 746 | self.assertEqual('http://subdomain.domain.com', f.clean('subdomain.domain.com')) |
| 747 | self.assertEqual('http://200.8.9.10', f.clean('http://200.8.9.10')) |
748 | 748 | self.assertEqual('http://200.8.9.10:8000/test', f.clean('http://200.8.9.10:8000/test')) |
749 | 749 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'foo') |
750 | 750 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://') |
… |
… |
class FieldsTests(SimpleTestCase):
|
757 | 757 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://-invalid.com') |
758 | 758 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://inv-.alid-.com') |
759 | 759 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://inv-.-alid.com') |
760 | | self.assertEqual('http://valid-----hyphens.com/', f.clean('http://valid-----hyphens.com')) |
| 760 | self.assertEqual('http://valid-----hyphens.com', f.clean('http://valid-----hyphens.com')) |
761 | 761 | self.assertEqual('http://some.idn.xyz\xe4\xf6\xfc\xdfabc.domain.com:123/blah', f.clean('http://some.idn.xyzäöüßabc.domain.com:123/blah')) |
762 | 762 | self.assertEqual('http://www.example.com/s/http://code.djangoproject.com/ticket/13804', f.clean('www.example.com/s/http://code.djangoproject.com/ticket/13804')) |
763 | 763 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, '[a') |
… |
… |
class FieldsTests(SimpleTestCase):
|
776 | 776 | f = URLField(required=False) |
777 | 777 | self.assertEqual('', f.clean('')) |
778 | 778 | self.assertEqual('', f.clean(None)) |
779 | | self.assertEqual('http://example.com/', f.clean('http://example.com')) |
780 | | self.assertEqual('http://www.example.com/', f.clean('http://www.example.com')) |
| 779 | self.assertEqual('http://example.com', f.clean('http://example.com')) |
| 780 | self.assertEqual('http://www.example.com', f.clean('http://www.example.com')) |
781 | 781 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'foo') |
782 | 782 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://') |
783 | 783 | self.assertRaisesMessage(ValidationError, "'Enter a valid URL.'", f.clean, 'http://example') |
… |
… |
class FieldsTests(SimpleTestCase):
|
787 | 787 | def test_urlfield_5(self): |
788 | 788 | f = URLField(min_length=15, max_length=20) |
789 | 789 | self.assertWidgetRendersTo(f, '<input id="id_f" type="url" name="f" maxlength="20" />') |
790 | | self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 15 characters (it has 13).'", f.clean, 'http://f.com') |
791 | | self.assertEqual('http://example.com/', f.clean('http://example.com')) |
792 | | self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 38).'", f.clean, 'http://abcdefghijklmnopqrstuvwxyz.com') |
| 790 | self.assertRaisesMessage(ValidationError, "'Ensure this value has at least 15 characters (it has 12).'", f.clean, 'http://f.com') |
| 791 | self.assertEqual('http://example.com', f.clean('http://example.com')) |
| 792 | self.assertRaisesMessage(ValidationError, "'Ensure this value has at most 20 characters (it has 37).'", f.clean, 'http://abcdefghijklmnopqrstuvwxyz.com') |
793 | 793 | |
794 | 794 | def test_urlfield_6(self): |
795 | 795 | f = URLField(required=False) |
796 | | self.assertEqual('http://example.com/', f.clean('example.com')) |
| 796 | self.assertEqual('http://example.com', f.clean('example.com')) |
797 | 797 | self.assertEqual('', f.clean('')) |
798 | | self.assertEqual('https://example.com/', f.clean('https://example.com')) |
| 798 | self.assertEqual('https://example.com', f.clean('https://example.com')) |
799 | 799 | |
800 | 800 | def test_urlfield_7(self): |
801 | 801 | f = URLField() |
802 | | self.assertEqual('http://example.com/', f.clean('http://example.com')) |
| 802 | self.assertEqual('http://example.com', f.clean('http://example.com')) |
803 | 803 | self.assertEqual('http://example.com/test', f.clean('http://example.com/test')) |
804 | 804 | |
805 | 805 | def test_urlfield_8(self): |