Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

17890: added support for extra_context in django.contrib.admin.site.password_change #499

Closed
wants to merge 12 commits into from

7 participants

@stephenmuss

This pull request replaces the one at #64.

Rebased my commits to be up to date with master branch.

Alex Gaynor and others added some commits
Alex Gaynor Added multi-column indexes to the 1.5 release notes.
957787a
Alex Gaynor Corrected a typo that inadvertently made its way into the docs.
0a49e61
@ptone ptone Fixed #19240 -- include pagination error details in ListView 404
Thanks to seawolf for the patch
5a00a57
@aisipos aisipos Fixed #18949 -- Improve performance of model_to_dict with many-to-many
When calling model_to_dict, improve performance of the generated SQL by
using values_list to determine primary keys of many to many objects. Add
a specific test for this function, test_model_to_dict_many_to_many

Thanks to brian for the original report and suggested fix.
e44ab5b
@alex alex Merge pull request #495 from aisipos/ticket_18949
Fixed #18949 -- Improve performance of model_to_dict with many-to-many
4d766b3
@pydanny pydanny Fixed #19241 -- Improved floatformat docs
Demonstrate how to round to integers using floatformat templatetag
a70492e
Bryan Veloso Merge pull request #496 from pydanny/ticket_19241
Demonstrate how to round to integers using floatformat templatetag
79a484f
@aisipos aisipos Fixed #18949 -- Fix broken test interactions in ModelForms tests
A test in Model Forms test was specifically referring to a fixed
primary key, which was now being used up in a newly committed.
This has been worked around by specifying a higher primary
key.
fdea262
@ptone ptone Removed redundant docs addition across two commits
d5c3c45f2fdfee09d81ad8dc7b0db8338d6d0aae

a70492e6b532905c921678f35b5c60b22387f1c6
2cb48ff
@ptone ptone Fixed py3 compatibility for 5a00a57aa591c766f5ee1d8c59b64618d74fe191
6bd6119
@claudep claudep Removed unnecessary import after b98083ce3d
39ec43b
@stephenmuss stephenmuss 17890: added support for extra_context in django.contrib.admin.site.p…
…assword_change
ed279fc
@timgraham timgraham commented on the diff
django/contrib/admin/sites.py
@@ -264,7 +264,8 @@ def password_change(self, request):
url = reverse('admin:password_change_done', current_app=self.name)
defaults = {
'current_app': self.name,
- 'post_change_redirect': url
+ 'post_change_redirect': url,
+ 'extra_context': extra_context
@timgraham Owner

should be extra_context or {}, (include a trailing comma)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@timgraham timgraham commented on the diff
tests/regressiontests/admin_views/customadmin.py
@@ -24,6 +24,9 @@ class Admin2(admin.AdminSite):
def index(self, request, extra_context=None):
return super(Admin2, self).index(request, {'foo': '*bar*'})
+ def password_change(self, request, extra_context={'EXTRA_CONTEXT': 'this is some extra context'}):
@timgraham Owner

pass the context like the index method above does. it's bad practice to include mutables (in this case a dictionary) as the default of a kwarg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@timgraham
Owner

As noted in the ticket, you'll need to update the docs including a ".. versionchanged:: 1.7" note as well as a mention in docs/releases/1.7.txt. Do you think you could make those updates?

@timgraham
Owner

Please open a new PR if you can update as per my comments, thanks!

@timgraham timgraham closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 4, 2012
  1. Added multi-column indexes to the 1.5 release notes.

    Alex Gaynor authored
  2. @ptone

    Fixed #19240 -- include pagination error details in ListView 404

    ptone authored
    Thanks to seawolf for the patch
  3. @aisipos

    Fixed #18949 -- Improve performance of model_to_dict with many-to-many

    aisipos authored
    When calling model_to_dict, improve performance of the generated SQL by
    using values_list to determine primary keys of many to many objects. Add
    a specific test for this function, test_model_to_dict_many_to_many
    
    Thanks to brian for the original report and suggested fix.
  4. @alex

    Merge pull request #495 from aisipos/ticket_18949

    alex authored
    Fixed #18949 -- Improve performance of model_to_dict with many-to-many
Commits on Nov 5, 2012
  1. @pydanny @ptone

    Fixed #19241 -- Improved floatformat docs

    pydanny authored ptone committed
    Demonstrate how to round to integers using floatformat templatetag
  2. Merge pull request #496 from pydanny/ticket_19241

    Bryan Veloso authored
    Demonstrate how to round to integers using floatformat templatetag
  3. @aisipos @ptone

    Fixed #18949 -- Fix broken test interactions in ModelForms tests

    aisipos authored ptone committed
    A test in Model Forms test was specifically referring to a fixed
    primary key, which was now being used up in a newly committed.
    This has been worked around by specifying a higher primary
    key.
  4. @ptone

    Removed redundant docs addition across two commits

    ptone authored
    d5c3c45f2fdfee09d81ad8dc7b0db8338d6d0aae
    
    a70492e6b532905c921678f35b5c60b22387f1c6
  5. @ptone
  6. @claudep
  7. @stephenmuss
This page is out of date. Refresh to see the latest.
View
5 django/contrib/admin/sites.py
@@ -256,7 +256,7 @@ def wrapper(*args, **kwargs):
def urls(self):
return self.get_urls(), self.app_name, self.name
- def password_change(self, request):
+ def password_change(self, request, extra_context=None):
"""
Handles the "change password" task -- both form display and validation.
"""
@@ -264,7 +264,8 @@ def password_change(self, request):
url = reverse('admin:password_change_done', current_app=self.name)
defaults = {
'current_app': self.name,
- 'post_change_redirect': url
+ 'post_change_redirect': url,
+ 'extra_context': extra_context
@timgraham Owner

should be extra_context or {}, (include a trailing comma)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
}
if self.password_change_template is not None:
defaults['template_name'] = self.password_change_template
View
1  django/contrib/contenttypes/generic.py
@@ -11,7 +11,6 @@
from django.db.models import signals
from django.db import models, router, DEFAULT_DB_ALIAS
from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
-from django.db.models.loading import get_model
from django.forms import ModelForm
from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance
from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets
View
2  django/forms/models.py
@@ -126,7 +126,7 @@ def model_to_dict(instance, fields=None, exclude=None):
data[f.name] = []
else:
# MultipleChoiceWidget needs a list of pks, not object instances.
- data[f.name] = [obj.pk for obj in f.value_from_object(instance)]
+ data[f.name] = list(f.value_from_object(instance).values_list('pk', flat=True))
else:
data[f.name] = f.value_from_object(instance)
return data
View
7 django/views/generic/list.py
@@ -50,9 +50,10 @@ def paginate_queryset(self, queryset, page_size):
try:
page = paginator.page(page_number)
return (paginator, page, page.object_list, page.has_other_pages())
- except InvalidPage:
- raise Http404(_('Invalid page (%(page_number)s)') % {
- 'page_number': page_number
+ except InvalidPage as e:
+ raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
+ 'page_number': page_number,
+ 'message': str(e)
})
def get_paginate_by(self, queryset):
View
4 docs/ref/models/options.txt
@@ -263,10 +263,10 @@ Django quotes column and table names behind the scenes.
``index_together``
-.. versionadded:: 1.5
-
.. attribute:: Options.index_together
+ .. versionadded:: 1.5
+
Sets of field names that, taken together, are indexed::
index_together = [
View
22 docs/ref/templates/builtins.txt
@@ -1505,27 +1505,27 @@ that many decimal places. For example:
``34.26000`` ``{{ value|floatformat:3 }}`` ``34.260``
============ ============================= ==========
-If the argument passed to ``floatformat`` is negative, it will round a number
-to that many decimal places -- but only if there's a decimal part to be
-displayed. For example:
+Particularly useful is passing 0 (zero) as the argument which will round the
+float to the nearest integer.
============ ================================ ==========
``value`` Template Output
============ ================================ ==========
-``34.23234`` ``{{ value|floatformat:"-3" }}`` ``34.232``
-``34.00000`` ``{{ value|floatformat:"-3" }}`` ``34``
-``34.26000`` ``{{ value|floatformat:"-3" }}`` ``34.260``
+``34.23234`` ``{{ value|floatformat:"0" }}`` ``34``
+``34.00000`` ``{{ value|floatformat:"0" }}`` ``34``
+``39.56000`` ``{{ value|floatformat:"0" }}`` ``40``
============ ================================ ==========
-If the argument passed to ``floatformat`` is 0 (zero), it will round the number
-to the nearest integer.
+If the argument passed to ``floatformat`` is negative, it will round a number
+to that many decimal places -- but only if there's a decimal part to be
+displayed. For example:
============ ================================ ==========
``value`` Template Output
============ ================================ ==========
-``34.23234`` ``{{ value|floatformat:"0" }}`` ``34``
-``34.00000`` ``{{ value|floatformat:"0" }}`` ``34``
-``39.56000`` ``{{ value|floatformat:"0" }}`` ``40``
+``34.23234`` ``{{ value|floatformat:"-3" }}`` ``34.232``
+``34.00000`` ``{{ value|floatformat:"-3" }}`` ``34``
+``34.26000`` ``{{ value|floatformat:"-3" }}`` ``34.260``
============ ================================ ==========
Using ``floatformat`` with no argument is equivalent to using ``floatformat``
View
4 docs/releases/1.5.txt
@@ -302,6 +302,10 @@ Django 1.5 also includes several smaller improvements worth noting:
* The :ref:`cache-based session backend <cached-sessions-backend>` can store
session data in a non-default cache.
+* Multi-column indexes can now be created on models. Read the
+ :attr:`~django.db.models.Options.index_together` documentation for more
+ information.
+
Backwards incompatible changes in 1.5
=====================================
View
41 tests/modeltests/model_forms/tests.py
@@ -561,6 +561,42 @@ def test_unique_for_date_with_nullable_date(self):
"slug": "Django 1.0"}, instance=p)
self.assertTrue(form.is_valid())
+class ModelToDictTests(TestCase):
+ """
+ Tests for forms.models.model_to_dict
+ """
+ def test_model_to_dict_many_to_many(self):
+ categories=[
+ Category(name='TestName1', slug='TestName1', url='url1'),
+ Category(name='TestName2', slug='TestName2', url='url2'),
+ Category(name='TestName3', slug='TestName3', url='url3')
+ ]
+ for c in categories:
+ c.save()
+ writer = Writer(name='Test writer')
+ writer.save()
+
+ art = Article(
+ headline='Test article',
+ slug='test-article',
+ pub_date=datetime.date(1988, 1, 4),
+ writer=writer,
+ article='Hello.'
+ )
+ art.save()
+ for c in categories:
+ art.categories.add(c)
+ art.save()
+
+ with self.assertNumQueries(1):
+ d = model_to_dict(art)
+
+ #Ensure all many-to-many categories appear in model_to_dict
+ for c in categories:
+ self.assertIn(c.pk, d['categories'])
+ #Ensure many-to-many relation appears as a list
+ self.assertIsInstance(d['categories'], list)
+
class OldFormForXTests(TestCase):
def test_base_form(self):
self.assertEqual(Category.objects.count(), 0)
@@ -1024,7 +1060,10 @@ def test_with_data(self):
# Add a Category object *after* the ModelMultipleChoiceField has already been
# instantiated. This proves clean() checks the database during clean() rather
# than caching it at time of instantiation.
- c6 = Category.objects.create(id=6, name='Sixth', url='6th')
+ # Note, we are using an id of 1006 here since tests that run before
+ # this may create categories with primary keys up to 6. Use
+ # a number that is will not conflict.
+ c6 = Category.objects.create(id=1006, name='Sixth', url='6th')
self.assertEqual(c6.name, 'Sixth')
self.assertQuerysetEqual(f.clean([c6.id]), ["Sixth"])
View
3  tests/regressiontests/admin_views/customadmin.py
@@ -24,6 +24,9 @@ class Admin2(admin.AdminSite):
def index(self, request, extra_context=None):
return super(Admin2, self).index(request, {'foo': '*bar*'})
+ def password_change(self, request, extra_context={'EXTRA_CONTEXT': 'this is some extra context'}):
@timgraham Owner

pass the context like the index method above does. it's bad practice to include mutables (in this case a dictionary) as the default of a kwarg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ return super(Admin2, self).password_change(request, extra_context)
+
def get_urls(self):
return patterns('',
(r'^my_view/$', self.admin_view(self.my_view)),
View
7 tests/regressiontests/admin_views/tests.py
@@ -781,6 +781,13 @@ def testCustomAdminSitePasswordChangeTemplate(self):
self.assertTemplateUsed(response, 'custom_admin/password_change_form.html')
self.assertContains(response, 'Hello from a custom password change form template')
+ def testCustomAdminSitePasswordChangeWithExtraContext(self):
+ "#17890: Test support for extra_context in password_change"
+ request = self.client.get('/test_admin/admin2/password_change/')
+ self.assertIsInstance(request, TemplateResponse)
+ self.assertTemplateUsed(request, 'custom_admin/password_change_form.html')
+ self.assertTrue('this is some extra context' in request.content)
+
def testCustomAdminSitePasswordChangeDoneTemplate(self):
response = self.client.get('/test_admin/admin2/password_change/done/')
self.assertIsInstance(response, TemplateResponse)
View
13 tests/regressiontests/generic_views/list.py
@@ -2,7 +2,9 @@
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
+from django.test.utils import override_settings
from django.views.generic.base import View
+from django.utils.encoding import force_str
from .models import Author, Artist
@@ -171,8 +173,17 @@ def test_paginated_list_view_does_not_load_entire_table(self):
with self.assertNumQueries(3):
self.client.get('/list/authors/notempty/paginated/')
+ @override_settings(DEBUG=True)
+ def test_paginated_list_view_returns_useful_message_on_invalid_page(self):
+ # test for #19240
+ # tests that source exception's message is included in page
+ self._make_authors(1)
+ res = self.client.get('/list/authors/paginated/2/')
+ self.assertEqual(res.status_code, 404)
+ self.assertEqual(force_str(res.context.get('reason')),
+ "Invalid page (2): That page contains no results")
+
def _make_authors(self, n):
Author.objects.all().delete()
for i in range(n):
Author.objects.create(name='Author %02i' % i, slug='a%s' % i)
-
View
1  tests/templates/custom_admin/password_change_form.html
@@ -2,5 +2,6 @@
{% block content %}
Hello from a custom password change form template
+{{ EXTRA_CONTEXT }}
{{ block.super }}
{% endblock %}
Something went wrong with that request. Please try again.