Ticket #5490: urlquote_string_primarekey_with_tests.diff
File urlquote_string_primarekey_with_tests.diff, 10.1 KB (added by , 16 years ago) |
---|
-
django/contrib/admin/options.py
15 15 from django.utils.text import capfirst, get_text_list 16 16 from django.utils.translation import ugettext as _ 17 17 from django.utils.encoding import force_unicode 18 from django.utils.http import urlquote, URL_SAFE_CHARACTERS 18 19 import sets 19 20 20 21 HORIZONTAL, VERTICAL = 1, 2 … … 680 681 681 682 # Populate deleted_objects, a data structure of all related objects that 682 683 # will also be deleted. 683 deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), force_unicode(object_id), escape(obj))), []]684 deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), urlquote(object_id, safe=URL_SAFE_CHARACTERS), escape(obj))), []] 684 685 perms_needed = sets.Set() 685 686 get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1, self.admin_site) 686 687 -
django/contrib/admin/models.py
4 4 from django.utils.translation import ugettext_lazy as _ 5 5 from django.utils.encoding import smart_unicode 6 6 from django.utils.safestring import mark_safe 7 from django.utils.http import urlquote, URL_SAFE_CHARACTERS 7 8 8 9 ADDITION = 1 9 10 CHANGE = 2 … … 50 51 Returns the admin URL to edit the object represented by this log entry. 51 52 This is relative to the Django admin index page. 52 53 """ 53 return mark_safe(u"%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, self.object_id))54 return mark_safe(u"%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, urlquote(self.object_id, safe=URL_SAFE_CHARACTERS))) -
django/contrib/admin/views/main.py
6 6 from django.utils.encoding import force_unicode, smart_str 7 7 from django.utils.translation import ugettext 8 8 from django.utils.safestring import mark_safe 9 from django.utils.http import urlencode 9 from django.utils.http import urlencode, urlquote, URL_SAFE_CHARACTERS 10 10 import operator 11 11 12 12 try: … … 246 246 return qs 247 247 248 248 def url_for_result(self, result): 249 return "%s/" % quote(getattr(result, self.pk_attname))249 return "%s/" % urlquote(getattr(result, self.pk_attname), safe=URL_SAFE_CHARACTERS) -
django/contrib/admin/templates/admin/index.html
59 59 {% else %} 60 60 <ul class="actionlist"> 61 61 {% for entry in admin_log %} 62 <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr |escape}}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span></li>62 <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span></li> 63 63 {% endfor %} 64 64 </ul> 65 65 {% endif %} -
django/utils/http.py
4 4 from django.utils.encoding import smart_str, force_unicode 5 5 from django.utils.functional import allow_lazy 6 6 7 # These are the safe characters as defined by: 8 # http://www.ietf.org/rfc/rfc2396.txt (see: 2.3. Unreserved Characters) 9 # these characters are safe to be used in a URL part. 10 URL_SAFE_CHARACTERS = "-_.!~*'()" 11 7 12 def urlquote(url, safe='/'): 8 13 """ 9 14 A version of Python's urllib.quote() function that can operate on unicode -
tests/regressiontests/admin_views/fixtures/string-primary-key.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="1" model="admin_views.modelwithstringprimarykey"> 4 <field type="CharField" name="id"><![CDATA[abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 -_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`]]></field> 5 </object> 6 </django-objects> 7 No newline at end of file -
tests/regressiontests/admin_views/tests.py
2 2 from django.test import TestCase 3 3 from django.contrib.auth.models import User, Permission 4 4 from django.contrib.contenttypes.models import ContentType 5 from django.contrib.admin.models import LogEntry 5 6 from django.contrib.admin.sites import LOGIN_FORM_KEY, _encode_post_data 6 7 7 8 # local test models 8 from models import Article, CustomArticle, Section 9 from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey 9 10 10 11 def get_perm(Model, perm): 11 12 """Return the permission object, for the Model""" … … 320 321 self.assertRedirects(post, '/test_admin/admin/') 321 322 self.failUnlessEqual(Article.objects.all().count(), 0) 322 323 self.client.get('/test_admin/admin/logout/') 323 324 No newline at end of file 324 325 class AdminViewStringPrimaryKeyTest(TestCase): 326 fixtures = ['admin-views-users.xml', 'string-primary-key.xml'] 327 328 def __init__(self, *args): 329 super(AdminViewStringPrimaryKeyTest, self).__init__(*args) 330 331 # The primary key value used is just a string containing all possible characters 332 self.pk = """abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 -_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`""" 333 334 self.pk_escaped = """abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 -_.!~*'() ;/?:@&=+$, <>#%" {}|\^[]`""" 335 336 # The characters that should be quoted are defined in: 337 # These are the safe characters as defined by: 338 # http://www.ietf.org/rfc/rfc2396.txt (see chapter 2) 339 # The safe characters are defined in django.util.http.URL_SAFE_CHARACTERS 340 self.pk_quoted = """abcdefghijklmnopqrstuvwxyz%20ABCDEFGHIJKLMNOPQRSTUVWXYZ%201234567890%20-_.!~*'()%20%3B%2F%3F%3A%40%26%3D%2B%24%2C%20%3C%3E%23%25%22%20%7B%7D%7C%5C%5E%5B%5D%60""" 341 342 def setUp(self): 343 self.client.login(username='super', password='secret') 344 345 # This entry refers to content type which is not known at the moment the fixture is imported 346 content_type_id = ContentType.objects.get_for_model(ModelWithStringPrimaryKey).id 347 ContentType.objects.all() 348 349 LogEntry.objects.log_action(100, content_type_id, self.pk, self.pk, 2, change_message='') 350 351 def tearDown(self): 352 self.client.logout() 353 354 def test_get_change_view(self): 355 "Retrieving the object using urlencoded form of primary key should work" 356 response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % self.pk_quoted) 357 358 self.assertContains(response, self.pk_escaped) 359 360 def test_changelist_to_changeform_link(self): 361 "The link from the changelist referring to the changeform of the object should be quoted" 362 response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/') 363 364 should_contain = """<tr class="row1"><th><a href="%s/">%s</a></th></tr>""" % (self.pk_quoted, self.pk_escaped) 365 self.assertContains(response, should_contain) 366 367 def test_recentactions_link(self): 368 "The link from the recent actions list referring to the changeform of the object should be quoted" 369 response = self.client.get('/test_admin/admin/') 370 371 should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (self.pk_quoted, self.pk_escaped) 372 self.assertContains(response, should_contain) 373 374 def test_deleteconfirmation_link(self): 375 "The link from the delete confirmation page referring back to the changeform of the object should be quoted" 376 response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/delete/' % self.pk_quoted) 377 378 should_contain = """<a href="../../%s/">%s</a>""" % (self.pk_quoted, self.pk_escaped) 379 self.assertContains(response, should_contain) 380 381 No newline at end of file -
tests/regressiontests/admin_views/models.py
48 48 'extra_var': 'Hello!' 49 49 } 50 50 ) 51 51 52 class ModelWithStringPrimaryKey(models.Model): 53 id = models.CharField(max_length='255', primary_key=True) 54 55 def __unicode__(self): 56 return self.id 57 52 58 admin.site.register(Article, ArticleAdmin) 53 59 admin.site.register(CustomArticle, CustomArticleAdmin) 54 60 admin.site.register(Section) 61 admin.site.register(ModelWithStringPrimaryKey)