mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Merge pull request #900 from bmispelon/ticket-20022
Fix #20022: Correctly handle prefixes with url-unsafe characters in reverse()
This commit is contained in:
		| @@ -388,7 +388,7 @@ class RegexURLResolver(LocaleRegexProvider): | ||||
|                     if len(args) != len(params) + len(prefix_args): | ||||
|                         continue | ||||
|                     unicode_args = [force_text(val) for val in args] | ||||
|                     candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args)) | ||||
|                     candidate = (prefix_norm.replace('%', '%%') + result) % dict(zip(prefix_args + params, unicode_args)) | ||||
|                 else: | ||||
|                     if set(kwargs.keys()) | set(defaults.keys()) != set(params) | set(defaults.keys()) | set(prefix_args): | ||||
|                         continue | ||||
|   | ||||
| @@ -10,29 +10,16 @@ from django.db import models | ||||
| from django.utils import six | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
|  | ||||
| from shared_models.models import Author, Book | ||||
|  | ||||
| class Author(models.Model): | ||||
|     name = models.CharField(max_length=100) | ||||
|     class Meta: | ||||
|         ordering = ('name', ) | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Article(models.Model): | ||||
|     headline = models.CharField(max_length=100) | ||||
|     pub_date = models.DateTimeField() | ||||
|     author = models.ForeignKey(Author, blank=True, null=True) | ||||
|     class Meta: | ||||
|         ordering = ('-pub_date', 'headline') | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.headline | ||||
|  | ||||
| class Tag(models.Model): | ||||
|     articles = models.ManyToManyField(Article) | ||||
|     articles = models.ManyToManyField(Book) | ||||
|     name = models.CharField(max_length=100) | ||||
|     class Meta: | ||||
|         ordering = ('name', ) | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Season(models.Model): | ||||
|     year = models.PositiveSmallIntegerField() | ||||
| @@ -41,6 +28,7 @@ class Season(models.Model): | ||||
|     def __str__(self): | ||||
|         return six.text_type(self.year) | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Game(models.Model): | ||||
|     season = models.ForeignKey(Season, related_name='games') | ||||
| @@ -50,6 +38,7 @@ class Game(models.Model): | ||||
|     def __str__(self): | ||||
|         return "%s at %s" % (self.away, self.home) | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Player(models.Model): | ||||
|     name = models.CharField(max_length=100) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -21,6 +21,7 @@ os.environ['DJANGO_TEST_TEMP_DIR'] = TEMP_DIR | ||||
| SUBDIRS_TO_SKIP = ['templates'] | ||||
|  | ||||
| ALWAYS_INSTALLED_APPS = [ | ||||
|     'shared_models', | ||||
|     'django.contrib.contenttypes', | ||||
|     'django.contrib.auth', | ||||
|     'django.contrib.sites', | ||||
|   | ||||
							
								
								
									
										0
									
								
								tests/shared_models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/shared_models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										30
									
								
								tests/shared_models/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/shared_models/models.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| from django.db import models | ||||
| from django.utils import timezone | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
|  | ||||
|  | ||||
| class Tag(models.Model): | ||||
|     name = models.CharField(max_length=255) | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Author(models.Model): | ||||
|     name = models.CharField(max_length=100) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Book(models.Model): | ||||
|     name = models.CharField(max_length=200) | ||||
|     pages = models.IntegerField(default=0) | ||||
|     author = models.ForeignKey(Author, null=True) | ||||
|     pubdate = models.DateTimeField() | ||||
|     tags = models.ManyToManyField(Tag) | ||||
|  | ||||
|     class Meta: | ||||
|         ordering = ['-pubdate', 'name'] | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
| @@ -1,18 +0,0 @@ | ||||
| from django.db import models | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Author(models.Model): | ||||
|     name = models.CharField(max_length=20) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class Book(models.Model): | ||||
|     name = models.CharField(max_length=20) | ||||
|     authors = models.ManyToManyField(Author) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|   | ||||
| @@ -3,7 +3,7 @@ from __future__ import absolute_import | ||||
| from django.db import models | ||||
| from django.test import TestCase | ||||
|  | ||||
| from .models import Author, Book | ||||
| from shared_models.models import Author, Book | ||||
|  | ||||
|  | ||||
| class SignalsRegressTests(TestCase): | ||||
| @@ -77,7 +77,7 @@ class SignalsRegressTests(TestCase): | ||||
|             "Is created" | ||||
|         ]) | ||||
|  | ||||
|         b1 = Book(name='Snow Crash') | ||||
|         b1 = Book(name='Snow Crash', pubdate='2012-02-02 12:00') | ||||
|         self.assertEqual(self.get_signal_output(b1.save), [ | ||||
|             "pre_save signal, Snow Crash", | ||||
|             "post_save signal, Snow Crash", | ||||
| @@ -87,7 +87,7 @@ class SignalsRegressTests(TestCase): | ||||
|     def test_m2m_signals(self): | ||||
|         """ Assigning and removing to/from m2m shouldn't generate an m2m signal """ | ||||
|  | ||||
|         b1 = Book(name='Snow Crash') | ||||
|         b1 = Book(name='Snow Crash', pubdate='2012-02-02 12:00') | ||||
|         self.get_signal_output(b1.save) | ||||
|         a1 = Author(name='Neal Stephenson') | ||||
|         self.get_signal_output(a1.save) | ||||
|   | ||||
| @@ -183,6 +183,11 @@ class URLPatternReverse(TestCase): | ||||
|         self.assertEqual('/bump%2520map/includes/non_path_include/', | ||||
|                reverse('non_path_include', prefix='/bump%20map/')) | ||||
|  | ||||
|     def test_non_urlsafe_prefix_with_args(self): | ||||
|         # Regression for #20022 | ||||
|         self.assertEqual('/%7Eme/places/1/', | ||||
|                 reverse('places', args=[1], prefix='/~me/')) | ||||
|  | ||||
| class ResolverTests(unittest.TestCase): | ||||
|     def test_resolver_repr(self): | ||||
|         """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user