Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16319 -- added SuccessMessageMixin to contrib.messages

Thanks martinogden for the initial patch and d1ffuz0r for tests.
  • Loading branch information...
commit 9a85ad89c20e88340cdba85b8e9f5806c95835db 1 parent 5938e70
Paul Collins authored March 18, 2013 ptone committed March 19, 2013
1  AUTHORS
@@ -607,6 +607,7 @@ answer newbie questions, and generally made Django that much better:
607 607
     Cheng Zhang
608 608
     Hannes Struß <x@hannesstruss.de>
609 609
     Deric Crago <deric.crago@gmail.com>
  610
+    Paul Collins <paul.collins.iii@gmail.com>
610 611
 
611 612
 A big THANK YOU goes to:
612 613
 
1  django/contrib/messages/tests/__init__.py
@@ -2,3 +2,4 @@
2 2
 from django.contrib.messages.tests.fallback import FallbackTest
3 3
 from django.contrib.messages.tests.middleware import MiddlewareTest
4 4
 from django.contrib.messages.tests.session import SessionTest
  5
+from django.contrib.messages.tests.mixins import SuccessMessageMixinTests
14  django/contrib/messages/tests/mixins.py
... ...
@@ -0,0 +1,14 @@
  1
+from django.test.testcases import TestCase
  2
+from django.contrib.messages.tests.urls import ContactFormViewWithMsg
  3
+from django.core.urlresolvers import reverse
  4
+
  5
+class SuccessMessageMixinTests(TestCase):
  6
+    urls = 'django.contrib.messages.tests.urls'
  7
+
  8
+    def test_set_messages_success(self):
  9
+        author = {'name': 'John Doe',
  10
+                  'slug': 'success-msg'}
  11
+        add_url = reverse('add_success_msg')
  12
+        req = self.client.post(add_url, author)
  13
+        self.assertIn(ContactFormViewWithMsg.success_message % author,
  14
+                      req.cookies['messages'].value)
18  django/contrib/messages/tests/urls.py
... ...
@@ -1,10 +1,13 @@
1  
-from django.conf.urls import patterns
  1
+from django.conf.urls import patterns, url
2 2
 from django.contrib import messages
3 3
 from django.core.urlresolvers import reverse
  4
+from django import forms
4 5
 from django.http import HttpResponseRedirect, HttpResponse
5 6
 from django.template import RequestContext, Template
6 7
 from django.template.response import TemplateResponse
7 8
 from django.views.decorators.cache import never_cache
  9
+from django.contrib.messages.views import SuccessMessageMixin
  10
+from django.views.generic.edit import FormView
8 11
 
9 12
 TEMPLATE = """{% if messages %}
10 13
 <ul class="messages">
@@ -49,8 +52,21 @@ def show(request):
49 52
 def show_template_response(request):
50 53
     return TemplateResponse(request, Template(TEMPLATE))
51 54
 
  55
+
  56
+class ContactForm(forms.Form):
  57
+    name = forms.CharField(required=True)
  58
+    slug = forms.SlugField(required=True)
  59
+
  60
+
  61
+class ContactFormViewWithMsg(SuccessMessageMixin, FormView):
  62
+    form_class = ContactForm
  63
+    success_url = show
  64
+    success_message = "%(name)s was created successfully"
  65
+
  66
+
52 67
 urlpatterns = patterns('',
53 68
     ('^add/(debug|info|success|warning|error)/$', add),
  69
+    url('^add/msg/$', ContactFormViewWithMsg.as_view(), name='add_success_msg'),
54 70
     ('^show/$', show),
55 71
     ('^template_response/add/(debug|info|success|warning|error)/$', add_template_response),
56 72
     ('^template_response/show/$', show_template_response),
19  django/contrib/messages/views.py
... ...
@@ -0,0 +1,19 @@
  1
+from django.views.generic.edit import FormMixin
  2
+from django.contrib import messages
  3
+
  4
+
  5
+class SuccessMessageMixin(FormMixin):
  6
+    """
  7
+    Adds a success message on successful form submission.
  8
+    """
  9
+    success_message = ''
  10
+
  11
+    def form_valid(self, form):
  12
+        response = super(SuccessMessageMixin, self).form_valid(form)
  13
+        success_message = self.get_success_message(form.cleaned_data)
  14
+        if success_message:
  15
+            messages.success(self.request, success_message)
  16
+        return response
  17
+
  18
+    def get_success_message(self, cleaned_data):
  19
+        return self.success_message % cleaned_data
47  docs/ref/contrib/messages.txt
@@ -286,6 +286,53 @@ example::
286 286
    use one of the ``add_message`` family of methods. It does not hide failures
287 287
    that may occur for other reasons.
288 288
 
  289
+Adding messages in Class Based Views
  290
+------------------------------------
  291
+
  292
+.. versionadded:: 1.6
  293
+
  294
+.. class:: django.contrib.messages.views.SuccessMessageMixin
  295
+
  296
+    Adds a success message attribute to
  297
+    :class:`~django.views.generic.edit.FormView` based classes
  298
+
  299
+    .. method:: get_success_message(cleaned_data)
  300
+
  301
+        ``cleaned_data`` is the cleaned data from the form which is used for
  302
+        string formatting
  303
+
  304
+**Example views.py**::
  305
+
  306
+    from django.contrib.messages.views import SuccessMessageMixin
  307
+    from django.views.generic.edit import CreateView
  308
+    from myapp.models import Author
  309
+
  310
+    class AuthorCreate(SuccessMessageMixin, CreateView):
  311
+        model = Author
  312
+        success_url = '/success/'
  313
+        success_message = "%(name)s was created successfully"
  314
+
  315
+The cleaned data from the ``form`` is available for string interpolation using
  316
+the ``%(field_name)s`` syntax. For ModelForms, if you need access to fields
  317
+from the saved ``object`` override the
  318
+:meth:`~django.contrib.messages.views.SuccessMessageMixin.get_success_message`
  319
+method.
  320
+
  321
+**Example views.py for ModelForms**::
  322
+
  323
+    from django.contrib.messages.views import SuccessMessageMixin
  324
+    from django.views.generic.edit import CreateView
  325
+    from myapp.models import ComplicatedModel
  326
+
  327
+    class ComplicatedCreate(SuccessMessageMixin, CreateView):
  328
+        model = ComplicatedModel
  329
+        success_url = '/success/'
  330
+        success_message = "%(calculated_field)s was created successfully"
  331
+
  332
+        def get_success_message(self, cleaned_data):
  333
+            return self.success_message % dict(cleaned_data,
  334
+                                               calculated_field=self.object.calculated_field)
  335
+
289 336
 Expiration of messages
290 337
 ======================
291 338
 
4  docs/releases/1.6.txt
@@ -126,6 +126,10 @@ Minor features
126 126
 * The ``MemcachedCache`` cache backend now uses the latest :mod:`pickle`
127 127
   protocol available.
128 128
 
  129
+* Added :class:`~django.contrib.messages.views.SuccessMessageMixin` which
  130
+  provides a ``success_message`` attribute for
  131
+  :class:`~django.view.generic.edit.FormView` based classes.
  132
+
129 133
 * Added the :attr:`django.db.models.ForeignKey.db_constraint` and
130 134
   :attr:`django.db.models.ManyToManyField.db_constraint` options.
131 135
 
1  tests/generic_views/views.py
... ...
@@ -1,6 +1,7 @@
1 1
 from __future__ import absolute_import
2 2
 
3 3
 from django.contrib.auth.decorators import login_required
  4
+from django.contrib.messages.views import SuccessMessageMixin
4 5
 from django.core.paginator import Paginator
5 6
 from django.core.urlresolvers import reverse, reverse_lazy
6 7
 from django.utils.decorators import method_decorator

0 notes on commit 9a85ad8

Please sign in to comment.
Something went wrong with that request. Please try again.