- Author:
- ubernostrum
- Posted:
- February 25, 2007
- Language:
- Python
- Version:
- Pre .96
- Score:
- 9 (after 9 ratings)
This is part of the user-registration code used on this site (see the django-registration project on Google Code for full source code), and shows a couple of interesting tricks you can do with manager methods.
In this case there's a separate RegistrationProfile
model used to store an activation key and expiration time for a new user's account, and the manager provides a couple of useful methods for working with them: create_inactive_user
creates a new user and a new RegistrationProfile
and emails an activation link, activate_user
knows how to activate a user's account, and delete_expired_users
knows how to clean out old accounts that were never activated.
Putting this code into custom manager methods helps a lot with re-use, because it means that this code doesn't have to be copied over into different views for each site which uses registration, and also makes more sense in terms of design, because these are methods which need to "know about" the model and work with it, and so they belong in a place close to the model.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | class RegistrationManager(models.Manager):
"""
Custom manager for the RegistrationProfile model.
The methods defined here provide shortcuts for account creation
and activation (including generation and emailing of activation
keys), and for cleaning out expired inactive accounts.
"""
def activate_user(self, activation_key):
"""
Given the activation key, makes a User's account active if the
activation key is valid and has not expired.
Returns the User if successful, or False if the account was
not found or the key had expired.
"""
# Make sure the key we're trying conforms to the pattern of a
# SHA1 hash; if it doesn't, no point even trying to look it up
# in the DB.
if re.match('[a-f0-9]{40}', activation_key):
try:
user_profile = self.get(activation_key=activation_key)
except self.model.DoesNotExist:
return False
if not user_profile.activation_key_expired():
# Account exists and has a non-expired key. Activate it.
user = user_profile.user
user.is_active = True
user.save()
return user
return False
def create_inactive_user(self, username, password, email, send_email=True):
"""
Creates a new User and a new RegistrationProfile for that
User, generates an activation key, and mails it.
Pass ``send_email=False`` to disable sending the email.
"""
# Create the user.
new_user = User.objects.create_user(username, email, password)
new_user.is_active = False
new_user.save()
# Generate a salted SHA1 hash to use as a key.
salt = sha.new(str(random.random())).hexdigest()[:5]
activation_key = sha.new(salt+new_user.username).hexdigest()
# And finally create the profile.
new_profile = self.create(user=new_user,
activation_key=activation_key)
if send_email:
from django.core.mail import send_mail
current_domain = Site.objects.get_current().domain
subject = "Activate your new account at %s" % current_domain
message_template = loader.get_template('registration/activation_email.txt')
message_context = Context({ 'site_url': 'http://%s/' % current_domain,
'activation_key': activation_key,
'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS })
message = message_template.render(message_context)
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [new_user.email])
return new_user
def delete_expired_users(self):
"""
Removes unused profiles and their associated accounts.
This is provided largely as a convenience for maintenance
purposes; if a RegistrationProfile's key expires without the
account being activated, then both the RegistrationProfile and
the associated User become clutter in the database, and (more
importantly) it won't be possible for anyone to ever come back
and claim the username. For best results, set this up to run
regularly as a cron job.
If you have a User whose account you want to keep in the
database even though it's inactive (say, to prevent a
troublemaker from accessing or re-creating his account), just
delete that User's RegistrationProfile and this method will
leave it alone.
"""
for profile in self.all():
if profile.activation_key_expired():
user = profile.user
if not user.is_active:
user.delete() # Removing the User will remove the RegistrationProfile, too.
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Is
activation_key_expired
a method and not a property? I think line #88 should read:#
FWIW, the pre & code markup rendered correctly in Preview, but posted as escaped HTML.
#
Please login first before commenting.