1. Jesaja Everling
  2. django-registration_appenginepatch

Commits

James Bennett  committed 16ebe5d

Custom signals are now sent on user registration and user activation. The profile_callback mechanism which previously served a similar purpose has been removed, so this is backwards-incompatible.

  • Participants
  • Parent commits 821b16e
  • Branches default

Comments (0)

Files changed (8)

File docs/forms.txt

View file
 
 Subclasses should feel free to add any additional validation they
 need, but should either preserve the base ``save()`` or implement a
-``save()`` which accepts the ``profile_callback`` keyword argument and
-passes it through to
-``RegistrationProfile.objects.create_inactive_user()``.
+``save()`` method which returns a ``User``.
     
 Fields:
 
 
 ``save()``
     Creates the new ``User`` and ``RegistrationProfile``, and returns
-    the ``User``.
-    
-    This is essentially a light wrapper around
-    ``RegistrationProfile.objects.create_inactive_user()``, feeding it
-    the form data and a profile callback (see the documentation on
-    ``create_inactive_user()`` for details) if supplied.
+    the ``User`` (by calling
+    ``RegistrationProfile.objects.create_inactive_user()``).
 
 
 Subclasses of ``RegistrationForm``

File docs/models.txt

View file
 Methods:
 
 ``activate_user(activation_key)``
-    Validates an activation key and activates the corresponding
+    Validate an activation key and activate the corresponding
     ``User`` if valid.
     
-    If the key is valid and has not expired, returns the ``User``
+    If the key is valid and has not expired, return the ``User``
     after activating.
     
-    If the key is not valid or has expired, returns ``False``.
+    If the key is not valid or has expired, return ``False``.
     
-    If the key is valid but the ``User`` is already active, returns
-    ``False``.
+    If the key is valid but the ``User`` is already active,
+    return ``False``.
     
-    To prevent reactivation of an account which has been deactivated
-    by site administrators, the activation key is reset to the string
-    ``ALREADY_ACTIVATED`` after successful activation.
+    To prevent reactivation of an account which has been
+    deactivated by site administrators, the activation key is
+    reset to the string constant ``RegistrationProfile.ACTIVATED``
+    after successful activation.
 
-``create_inactive_user(username, password, email, send_email=True, profile_callback=None)``
-    Creates a new, inactive ``User``, generates a
-    ``RegistrationProfile`` and emails its activation key to the
-    ``User``. Returns the new ``User``.
+    To execute customized logic when a ``User`` is activated,
+    connect a function to the signal
+    ``registration.signals.user_activated``; this signal will be
+    sent (with the ``User`` as the value of the keyword argument
+    ``user``) after a successful activation.
+
+``create_inactive_user(username, password, email, send_email=True)``
+    Create a new, inactive ``User``, generate a
+    ``RegistrationProfile`` and email its activation key to the
+    ``User``, returning the new ``User``.
     
     To disable the email, call with ``send_email=False``.
-    
+
     The activation email will make use of two templates:
 
     ``registration/activation_email_subject.txt``
         This template will be used for the subject line of the
-        email. It receives one context variable, ``site``, which is
-        the currently-active ``django.contrib.sites.models.Site``
-        instance. Because it is used as the subject line of an email,
-        this template's output **must** be only a single line of text;
-        output longer than one line will be forcibly joined into only
-        a single line.
+        email. It receives one context variable, ``site``, which
+        is the currently-active
+        ``django.contrib.sites.models.Site`` instance. Because it
+        is used as the subject line of an email, this template's
+        output **must** be only a single line of text; output
+        longer than one line will be forcibly joined into only a
+        single line.
 
     ``registration/activation_email.txt``
-        This template will be used for the body of the email. It will
-        receive three context variables: ``activation_key`` will be
-        the user's activation key (for use in constructing a URL to
-        activate the account), ``expiration_days`` will be the number
-        of days for which the key will be valid and ``site`` will be
-        the currently-active ``django.contrib.sites.models.Site``
-        instance.
+        This template will be used for the body of the email. It
+        will receive three context variables: ``activation_key``
+        will be the user's activation key (for use in constructing
+        a URL to activate the account), ``expiration_days`` will
+        be the number of days for which the key will be valid and
+        ``site`` will be the currently-active
+        ``django.contrib.sites.models.Site`` instance.
+
+    To execute customized logic once the new ``User`` has been
+    created, connect a function to the signal
+    ``registration.signals.user_registered``; this signal will be
+    sent (with the new ``User`` as the value of the keyword
+    argument ``user``) after the ``User`` and
+    ``RegistrationProfile`` have been created, and after the email (if
+    any) has been sent.
         
-    To enable creation of a custom user profile along with the
-    ``User`` (e.g., the model specified in the ``AUTH_PROFILE_MODULE``
-    setting), define a function which knows how to create and save an
-    instance of that model with appropriate default values, and pass
-    it as the keyword argument ``profile_callback``. This function
-    should accept one keyword argument:
-    
-    ``user``
-        The ``User`` to relate the profile to.
-
 ``create_profile(user)``
     Creates a ``RegistrationProfile`` for a given ``User``. Returns
     the ``RegistrationProfile``.

File docs/views.txt

View file
 By default, ``registration.forms.RegistrationForm`` will be used as
 the registration form; to change this, pass a different form class as
 the ``form_class`` keyword argument. The form class you specify must
-have a method ``save`` which will create and return the new ``User``,
-and that method must accept the keyword argument ``profile_callback``
-(see below).
-
-To enable creation of a site-specific user profile object for the new
-user, pass a function which will create the profile object as the
-keyword argument ``profile_callback``. See
-``RegistrationManager.create_inactive_user`` in the file ``models.py``
-for details on how to write this function.
+have a method ``save`` which will create and return the new ``User``.
 
 By default, use the template ``registration/registration_form.html``;
 to change this, pass the name of a template as the keyword argument
     callable object in this dictionary will be called to produce the
     end result which appears in the context.
 
-``profile_callback``
-    A function which will be used to create a site-specific profile
-    instance for the new ``User``.
-
 ``success_url``
     The URL to redirect to on successful registration.
 

File registration/forms.py

View file
     
     Subclasses should feel free to add any additional validation they
     need, but should either preserve the base ``save()`` or implement
-    a ``save()`` which accepts the ``profile_callback`` keyword
-    argument and passes it through to
-    ``RegistrationProfile.objects.create_inactive_user()``.
+    a ``save()`` method which returns a ``User``.
     
     """
     username = forms.RegexField(regex=r'^\w+$',
                 raise forms.ValidationError(_(u'You must type the same password each time'))
         return self.cleaned_data
     
-    def save(self, profile_callback=None):
+    def save(self):
         """
         Create the new ``User`` and ``RegistrationProfile``, and
-        returns the ``User``.
-        
-        This is essentially a light wrapper around
-        ``RegistrationProfile.objects.create_inactive_user()``,
-        feeding it the form data and a profile callback (see the
-        documentation on ``create_inactive_user()`` for details) if
-        supplied.
+        returns the ``User`` (by calling
+        ``RegistrationProfile.objects.create_inactive_user()``).
         
         """
         new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'],
                                                                     password=self.cleaned_data['password1'],
-                                                                    email=self.cleaned_data['email'],
-                                                                    profile_callback=profile_callback)
+                                                                    email=self.cleaned_data['email'])
         return new_user
 
 

File registration/models.py

View file
         
         To prevent reactivation of an account which has been
         deactivated by site administrators, the activation key is
-        reset to the string ``ALREADY_ACTIVATED`` after successful
-        activation.
+        reset to the string constant ``RegistrationProfile.ACTIVATED``
+        after successful activation.
+
+        To execute customized logic when a ``User`` is activated,
+        connect a function to the signal
+        ``registration.signals.user_activated``; this signal will be
+        sent (with the ``User`` as the value of the keyword argument
+        ``user``) after a successful activation.
         
         """
+        from registration.signals import user_activated
+        
         # Make sure the key we're trying conforms to the pattern of a
         # SHA1 hash; if it doesn't, no point trying to look it up in
         # the database.
                 user.save()
                 profile.activation_key = self.model.ACTIVATED
                 profile.save()
+                user_activated.send(sender=self.model, user=user)
                 return user
         return False
     
     def create_inactive_user(self, username, password, email,
-                             send_email=True, profile_callback=None):
+                             send_email=True):
         """
-        Create a new, inactive ``User``, generates a
+        Create a new, inactive ``User``, generate a
         ``RegistrationProfile`` and email its activation key to the
         ``User``, returning the new ``User``.
         
             be the number of days for which the key will be valid and
             ``site`` will be the currently-active
             ``django.contrib.sites.models.Site`` instance.
-        
-        To enable creation of a custom user profile along with the
-        ``User`` (e.g., the model specified in the
-        ``AUTH_PROFILE_MODULE`` setting), define a function which
-        knows how to create and save an instance of that model with
-        appropriate default values, and pass it as the keyword
-        argument ``profile_callback``. This function should accept one
-        keyword argument:
 
-        ``user``
-            The ``User`` to relate the profile to.
+        To execute customized logic once the new ``User`` has been
+        created, connect a function to the signal
+        ``registration.signals.user_registered``; this signal will be
+        sent (with the new ``User`` as the value of the keyword
+        argument ``user``) after the ``User`` and
+        ``RegistrationProfile`` have been created, and the email (if
+        any) has been sent..
         
         """
+        from registration.signals import user_registered
+
         new_user = User.objects.create_user(username, email, password)
         new_user.is_active = False
         new_user.save()
         
         registration_profile = self.create_profile(new_user)
         
-        if profile_callback is not None:
-            profile_callback(user=new_user)
-        
         if send_email:
             from django.core.mail import send_mail
             current_site = Site.objects.get_current()
                                          'site': current_site })
             
             send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [new_user.email])
+        user_registered.send(sender=self.model, user=new_user)
         return new_user
     create_inactive_user = transaction.commit_on_success(create_inactive_user)
     
     While it is possible to use this model as the value of the
     ``AUTH_PROFILE_MODULE`` setting, it's not recommended that you do
     so. This model's sole purpose is to store data temporarily during
-    account registration and activation, and a mechanism for
-    automatically creating an instance of a site-specific profile
-    model is provided via the ``create_inactive_user`` on
-    ``RegistrationManager``.
+    account registration and activation.
     
     """
     ACTIVATED = u"ALREADY_ACTIVATED"

File registration/signals.py

View file
+from django.dispatch import Signal
+
+
+# A new user has registered.
+user_registered = Signal(providing_args=["user"])
+
+# A user has activated his or her account.
+user_activated = Signal(providing_args=["user"])

File registration/tests.py

View file
 
 from registration import forms
 from registration.models import RegistrationProfile
+from registration import signals
 
 
 class RegistrationTestCase(TestCase):
         form = forms.RegistrationFormNoFreeEmail(data=base_data)
         self.failUnless(form.is_valid())
 
+    def test_signals(self):
+        """
+        Test that the ``user_registered`` and ``user_activated``
+        signals are sent, and that they send the ``User`` as an
+        argument.
+        
+        """
+        def receiver(sender, **kwargs):
+            self.assert_('user' in kwargs)
+            self.assertEqual(kwargs['user'].username, u'signal_test')
+            received_signals.append(kwargs.get('signal'))
+
+        received_signals = []
+        expected_signals = [signals.user_registered, signals.user_activated]
+        for signal in expected_signals:
+            signal.connect(receiver)
+
+        RegistrationProfile.objects.create_inactive_user(username='signal_test',
+                                                         password='foo',
+                                                         email='nobody@example.com',
+                                                         send_email=False)
+        RegistrationProfile.objects.activate_user(RegistrationProfile.objects.get(user__username='signal_test').activation_key)
+
+        self.assertEqual(received_signals, expected_signals)
+
 
 class RegistrationViewTests(RegistrationTestCase):
     """

File registration/views.py

View file
 
 
 def register(request, success_url=None,
-             form_class=RegistrationForm, profile_callback=None,
+             form_class=RegistrationForm,
              template_name='registration/registration_form.html',
              extra_context=None):
     """
     as the registration form; to change this, pass a different form
     class as the ``form_class`` keyword argument. The form class you
     specify must have a method ``save`` which will create and return
-    the new ``User``, and that method must accept the keyword argument
-    ``profile_callback`` (see below).
-    
-    To enable creation of a site-specific user profile object for the
-    new user, pass a function which will create the profile object as
-    the keyword argument ``profile_callback``. See
-    ``RegistrationManager.create_inactive_user`` in the file
-    ``models.py`` for details on how to write this function.
+    the new ``User``.
     
     By default, use the template
     ``registration/registration_form.html``; to change this, pass the
         callable object in this dictionary will be called to produce
         the end result which appears in the context.
     
-    ``profile_callback``
-        A function which will be used to create a site-specific
-        profile instance for the new ``User``.
-    
     ``success_url``
         The URL to redirect to on successful registration.
     
     if request.method == 'POST':
         form = form_class(data=request.POST, files=request.FILES)
         if form.is_valid():
-            new_user = form.save(profile_callback=profile_callback)
+            new_user = form.save()
             # success_url needs to be dynamically generated here; setting a
             # a default value using reverse() will cause circular-import
             # problems with the default URLConf for this application, which