diff --git a/django/core/validators.py b/django/core/validators.py index 4b9ab1f602..225dd5cba2 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -44,7 +44,7 @@ class URLValidator(RegexValidator): r'localhost|' #localhost... r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip r'(?::\d+)?' # optional port - r'(?:/?|/\S+)$', re.IGNORECASE) + r'(?:/?|[/?]\S+)$', re.IGNORECASE) def __init__(self, verify_exists=False, validator_user_agent=URL_VALIDATOR_USER_AGENT): super(URLValidator, self).__init__() diff --git a/django/forms/fields.py b/django/forms/fields.py index 4b4594a5c2..3197260fb6 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -551,12 +551,15 @@ class URLField(CharField): self.validators.append(validators.URLValidator(verify_exists=verify_exists, validator_user_agent=validator_user_agent)) def to_python(self, value): - # If no URL scheme given, assume http:// - if value and '://' not in value: - value = u'http://%s' % value - # If no URL path given, assume / - if value and not urlparse.urlsplit(value)[2]: - value += '/' + if value: + if '://' not in value: + # If no URL scheme given, assume http:// + value = u'http://%s' % value + url_fields = list(urlparse.urlsplit(value)) + if not url_fields[2]: + # the path portion may need to be added before query params + url_fields[2] = '/' + value = urlparse.urlunsplit(url_fields) return super(URLField, self).to_python(value) class BooleanField(Field): diff --git a/tests/modeltests/validators/tests.py b/tests/modeltests/validators/tests.py index de4d94f1af..331f6f0b61 100644 --- a/tests/modeltests/validators/tests.py +++ b/tests/modeltests/validators/tests.py @@ -106,6 +106,8 @@ SIMPLE_VALIDATORS_VALUES = ( (URLValidator(), 'http://200.8.9.10/', None), (URLValidator(), 'http://200.8.9.10:8000/test', None), (URLValidator(), 'http://valid-----hyphens.com/', None), + (URLValidator(), 'http://example.com?something=value', None), + (URLValidator(), 'http://example.com/index.php?something=value&another=value2', None), (URLValidator(), 'foo', ValidationError), (URLValidator(), 'http://', ValidationError), diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index 9bf6022e3f..2efe72d02c 100644 --- a/tests/regressiontests/forms/fields.py +++ b/tests/regressiontests/forms/fields.py @@ -496,6 +496,10 @@ class TestFields(TestCase): f = URLField() self.assertEqual(u'http://example.com/', f.clean('http://example.com')) self.assertEqual(u'http://example.com/test', f.clean('http://example.com/test')) + + def test_urlfield_ticket11826(self): + f = URLField() + self.assertEqual(u'http://example.com/?some_param=some_value', f.clean('http://example.com?some_param=some_value')) # BooleanField ################################################################