Fixed #16319 -- added SuccessMessageMixin to contrib.messages

Thanks martinogden for the initial patch and d1ffuz0r for tests.
This commit is contained in:
Paul Collins 2013-03-18 15:48:47 -07:00 committed by Preston Holmes
parent 5938e7013e
commit 9a85ad89c2
8 changed files with 104 additions and 1 deletions

View File

@ -607,6 +607,7 @@ answer newbie questions, and generally made Django that much better:
Cheng Zhang
Hannes Struß <x@hannesstruss.de>
Deric Crago <deric.crago@gmail.com>
Paul Collins <paul.collins.iii@gmail.com>
A big THANK YOU goes to:

View File

@ -2,3 +2,4 @@ from django.contrib.messages.tests.cookie import CookieTest
from django.contrib.messages.tests.fallback import FallbackTest
from django.contrib.messages.tests.middleware import MiddlewareTest
from django.contrib.messages.tests.session import SessionTest
from django.contrib.messages.tests.mixins import SuccessMessageMixinTests

View File

@ -0,0 +1,14 @@
from django.test.testcases import TestCase
from django.contrib.messages.tests.urls import ContactFormViewWithMsg
from django.core.urlresolvers import reverse
class SuccessMessageMixinTests(TestCase):
urls = 'django.contrib.messages.tests.urls'
def test_set_messages_success(self):
author = {'name': 'John Doe',
'slug': 'success-msg'}
add_url = reverse('add_success_msg')
req = self.client.post(add_url, author)
self.assertIn(ContactFormViewWithMsg.success_message % author,
req.cookies['messages'].value)

View File

@ -1,10 +1,13 @@
from django.conf.urls import patterns
from django.conf.urls import patterns, url
from django.contrib import messages
from django.core.urlresolvers import reverse
from django import forms
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext, Template
from django.template.response import TemplateResponse
from django.views.decorators.cache import never_cache
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import FormView
TEMPLATE = """{% if messages %}
<ul class="messages">
@ -49,8 +52,21 @@ def show(request):
def show_template_response(request):
return TemplateResponse(request, Template(TEMPLATE))
class ContactForm(forms.Form):
name = forms.CharField(required=True)
slug = forms.SlugField(required=True)
class ContactFormViewWithMsg(SuccessMessageMixin, FormView):
form_class = ContactForm
success_url = show
success_message = "%(name)s was created successfully"
urlpatterns = patterns('',
('^add/(debug|info|success|warning|error)/$', add),
url('^add/msg/$', ContactFormViewWithMsg.as_view(), name='add_success_msg'),
('^show/$', show),
('^template_response/add/(debug|info|success|warning|error)/$', add_template_response),
('^template_response/show/$', show_template_response),

View File

@ -0,0 +1,19 @@
from django.views.generic.edit import FormMixin
from django.contrib import messages
class SuccessMessageMixin(FormMixin):
"""
Adds a success message on successful form submission.
"""
success_message = ''
def form_valid(self, form):
response = super(SuccessMessageMixin, self).form_valid(form)
success_message = self.get_success_message(form.cleaned_data)
if success_message:
messages.success(self.request, success_message)
return response
def get_success_message(self, cleaned_data):
return self.success_message % cleaned_data

View File

@ -286,6 +286,53 @@ example::
use one of the ``add_message`` family of methods. It does not hide failures
that may occur for other reasons.
Adding messages in Class Based Views
------------------------------------
.. versionadded:: 1.6
.. class:: django.contrib.messages.views.SuccessMessageMixin
Adds a success message attribute to
:class:`~django.views.generic.edit.FormView` based classes
.. method:: get_success_message(cleaned_data)
``cleaned_data`` is the cleaned data from the form which is used for
string formatting
**Example views.py**::
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(SuccessMessageMixin, CreateView):
model = Author
success_url = '/success/'
success_message = "%(name)s was created successfully"
The cleaned data from the ``form`` is available for string interpolation using
the ``%(field_name)s`` syntax. For ModelForms, if you need access to fields
from the saved ``object`` override the
:meth:`~django.contrib.messages.views.SuccessMessageMixin.get_success_message`
method.
**Example views.py for ModelForms**::
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import ComplicatedModel
class ComplicatedCreate(SuccessMessageMixin, CreateView):
model = ComplicatedModel
success_url = '/success/'
success_message = "%(calculated_field)s was created successfully"
def get_success_message(self, cleaned_data):
return self.success_message % dict(cleaned_data,
calculated_field=self.object.calculated_field)
Expiration of messages
======================

View File

@ -126,6 +126,10 @@ Minor features
* The ``MemcachedCache`` cache backend now uses the latest :mod:`pickle`
protocol available.
* Added :class:`~django.contrib.messages.views.SuccessMessageMixin` which
provides a ``success_message`` attribute for
:class:`~django.view.generic.edit.FormView` based classes.
* Added the :attr:`django.db.models.ForeignKey.db_constraint` and
:attr:`django.db.models.ManyToManyField.db_constraint` options.

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import
from django.contrib.auth.decorators import login_required
from django.contrib.messages.views import SuccessMessageMixin
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse, reverse_lazy
from django.utils.decorators import method_decorator