django-registration update

An entry published by James Bennett on September 19, 2007, Part of the categories Django and Meta. 14 comments posted.

For those of you who are using/following it, I’ve just pushed out django-registration 0.3. The basic workflow of the application is still the same:

  1. User signs up for account.
  2. User receives activation email.
  3. User clicks link in email to activate account.

But under the hood quite a few things have been rearranged to make the application cleaner and more extensible, and there have been a couple of backwards-incompatible changes for anyone using an older version. Here’s how it breaks down.

Backwards-incompatible changes

You’ll now need to create one extra template — registration/activation_email_subject.txt — in order to use the activation emails. I’d gotten a number of requests to make this more configurable, and the solution I finally settled on was to use a template for the subject. One caveat you need to be aware of: because this is going to end up in the Subject: header of an email, it must render to a single line (multi-line subjects don’t work), and this will be enforced by the application; if your template renders to multiple lines, they will be collapsed into a single line for use in the email subject.

Also, if you were relying on the tos field in RegistrationForm you’ll need to make a small change: that field has been removed, and the ability to choose a form for the registration process has been added. A new class, RegistrationFormTermsOfService, provides the same behavior as the original RegistrationForm, so you can switch to using that and keep on going.

Finally, the context passed to the template for the activation email’s body has been changed: instead of the current_site variable containing only the domain, the variable site is now available and holds the full current Site object.

Configurable form classes

As mentioned above, you can now choose a form to use for the registration process, by passing the keyword argument form_class to the register view; this defaults to RegistrationForm. The only real requirement is that your form class (and you must pass the class, not an instance of it) must have a save() method which accepts the optional keyword argument profile_callback and which returns a User object.

Since this is now configurable, I’ve added a few example subclasses of RegistrationForm which provide useful variations on the registration process:

Any of these, or any other form class (whether it subclasses RegistrationForm or not, though that’s the easy way to do things) which implements save() as described above will work with the register view. This is useful both for customized registration logic, and for offering different types of registration (by mapping different URL patterns, with different values for the form_class argument, to the register view) to different classes of visitors.

Configurable templates

Both the register and activate views now accept an optional keyword argument template_name, just like Django’s built-in generic views. The defaults are still registration/registration_form.html and registration/activate.html, respectively, but again this adds flexibility for additional customization and opens up the possiblity of displaying different registration systems to different people.

Easy maintenance

There’s been a method — RegistrationProfile.objects.delete_expired_users() — for cleaning out user accounts which were never registered, but it’s never been particularly easy to use it in any sort of automated way. With this release, a script suitable for running as a cron job — registration/bin/delete_expired_users.py — has been added which will take care of this, and it includes instructions on how to add the appropriate line to your crontab.

This is intended to serve as a substitute for the need to reset registration profiles or re-send activation emails: if a user doesn’t receive or doesn’t act on the initial email, their inactive account will be deleted once it expires and they can register again.

Documentation

The bundled documentation has also been significantly expanded; I’ve always been a stickler for giving everything a useful docstring, but the files in the docs/ directory have been greatly expanded and now provide reasonably good standalone documentation for the entire application.

Unicode updates

Since Django’s Unicode branch has been merged for a while, and things seem to be pretty stable, I’ve gone ahead and updated django-registration to work properly in a Unicode-aware Django. This means that RegistrationProfile now defines __unicode__() instead of __str__(), and that the Unicode-aware versions of various utility functions are now used throughout the app.

Internationalization

And the big one that quite a few people have been waiting for: all (I hope) of the relevant strings in django-registration have now been marked for translation, and a conf directory has been added to hold translations. I know more than a couple folks have been hounding me about this since I release the very first version, and now that the Unicode branch is in and the app is updated to deal with that, it’s time to start opening up to internationalization.

Updated September 21: Looks like I misread the i18n docs. I’ve moved this to “locale” as is apparently needed for app-level i18n. You might want to “svn up” or download a fresh copy of the package.

The future

I’ve done some light testing and everything seems to work, but I can’t make any guarantees and I’d like to remind anyone who’s updating that django-registration is still officially beta software; if you discover bugs, please report them and I’ll get them fixed as soon as possible. Going forward, my plan is to shake out any remaining bugs, hopefully collect a few translations and then roll a 1.0 release; at this point I think the API is stable, with just the right amount of room for customization and extension, so once the code is known to be good and the internationalization opportunities have been explored, I’ll be ready to commit to maintaining a stable, production version.

On September 19, 2007, Jeff Croft said:

Great updates. Thanks so much for continuing to support this app!

On September 20, 2007, Samuel Adam said:

Yeah, with internationalization inside ! o/

I agree with Jeff, this is a very clean and useful app, keep committing !

Thanks a lot !

On September 20, 2007, David, biologeek said:

Once it’s 1.0, what about django.contrib.registration? :)

Anyway, thanks for the i18n.

On September 20, 2007, Pedro Furtado said:

Nice app!!! Thans a lot for the internationalization update!

One thing: isn’t the “locale” dir supposed to be in the root of the project or app directory?

On September 20, 2007, James Bennett said:

Pedro, according to Django’s internationalization docs:

It creates (or updates) a message file in the directory conf/locale. In the de example, the file will be conf/locale/de/LC_MESSAGES/django.po.

Hence I added conf/locale (and it appeared to work correctly, since I was able to create the “dummy” English translation files that are now bundled with the app, and someone else has already emailed me a working French translation).

On September 20, 2007, Pedro Furtado said:

My doubt was also based on i18n docs: >If run over your project source tree or your application source tree, it will do the >same, but the location of the locale directory is locale/LANG/LC_MESSAGES (note >the missing conf prefix). Anyway, this is just a detail.

On September 20, 2007, James Bennett said:

Hm. Looking at #5437 now, because apparently there’s some confusion over this.

On September 23, 2007, Alaa Salman said:

Hi,

Thanks for a great app. There’s something that i thought i’d check before reporting it as an issue.

In the views.py, the activate function’s documentation said that we can pass a keyword argument “template_name” but the implementation doesn’t seem to reflect that and always renders “registration/activate.html”.

I haven’t tried this myself to see if it works as documented, i am using the app with defaults. Am i misreading it or is this an oversight in the implementation?

Regards, Alaa Salman

On September 23, 2007, James Bennett said:

Yep, I got the wrong version of that committed accidentally. Fixed now.

On September 25, 2007, JoeCotellese said:

This may seem like a dumb question but it isn’t obvious how I would instantiate one of the subclassed forms.

I have a user profile module which has some additional fields. I need to put them into a form. Can’t really tell where I need to do this.

Thanks by the way, saved me some time.

On September 27, 2007, Joe said:

How email sends is changed … so activation_email.txt has a missing {{ site_url }} in its context.

— joe

On September 27, 2007, James Bennett said:

Joe, yes, that’s why I have this listed in the “backwards-incompatible changes” section (and in a similar section in the django-registration changelog file):

Finally, the context passed to the template for the activation email’s body has been changed: instead of the current_site variable containing only the domain, the variable site is now available and holds the full current Site object.

The example template’s been updated, but honestly at this point I think I’m just going to remove the example templates entirely; too many people ignore the glaring warning not to try to use them unmodified.

On October 13, 2007, Sridhar Ratnakumar said:

Is there not a way to get a reference to the full activation url in the template instead of just the activation code?

On October 13, 2007, James Bennett said:

Yes, use the “url” tag.

Comments for this entry are closed. If you'd like to share your thoughts on this entry with me, please contact me directly.

ponybadge