views:

40

answers:

2

I'm rolling my own custom registration module in Django based on django.contrib.auth. My registration module will have some extra functionality and help me reduce my dependency on other django modules that I'm currently using like django-registration and django-emailchange. I've run into a what-the-best-way-to-do-it problem here.

Note: All the user accounts are based on django.contrib.auth.models.User model.

When the user clicks the "sign-up" link, the request gets passed to my view named register. I have a custom form which has four fields — username, email, password1 and password2. The form is based on django.forms.Form. The form provides basic validation e.g. passoword1 and password2 are the email; the email/username do not exist.

When the data gets POSTed back to my register view, I call the is_valid() method of the form, after which, I create a new user by calling a Manager method called create_user() in django.contrib.auth.models.UserManager. I need to add more custom functionality at this point like sending activation emails, etc. As a best-practice method, where should this logic be? Should this be in a method of the User Model? Should it be where it is currently - the Manager of the Model? Or should this be placed into a custom save() method of my sign-up Form?

Thanks.

A: 

My recommendation is to not re-solve a problem that django-registration solves quite nicely. It has a pluggable backend system that lets you customize it as much or as little as needed.

Chris Lawlor
+1  A: 

Different from Chris, I believe on the philosophy of fat models, thin views.

The more code you can factor inside models, the more reusable your codebase is. Views concerns should be simply managing the request/response cycle and dealing with GET/POST parameters.

In this case, sending activation emails is related to the event of creating a new User. For those cases, Django already provides this abstraction through signals.

http://docs.djangoproject.com/en/1.2/topics/signals/#topics-signals

So, as an example, you can have in your models.py:

from django.contrib.models import User
from django.db.models.signals import post_save

def send_welcome_email(self):
   # Reusable email sending code

User.send_welcome_email = send_welcome_email

def welcome_emails(sender, instance, created, **kwargs):
    if created:
        instance.send_welcome_email() # `instance` is User

post_save.connect(welcome_emails, sender=User)

Similarly, you can have this for when a User is deleted, or everytime a User is saved, etc. Signals are a good abstraction to event-driven tasks.

hcalves
Good answer. I was really thinking "Don't put it in the save method", but after re-reading my answer I didn't explain it that way. Rather than rewrite it I'm retracting that part.
Chris Lawlor