Search code examples
databasedjangoviewactivation

Activation link to allow committing to database in Django


So I have an app that takes a form, and sends and e-mail address to somebody, but I want a way to stick and activation URL generated by Django into that e-mail, and not have the form data commit to the database until that activation link is clicked. Is there any way to do this?


Solution

  • Based on the comments on my first answer, here's a reworked one more suited to your needs.

    Create a model, e.g. ServiceHours, that next to the data you want to collect (hours done, supervisor_email, ...), has the following fields:

    activation_key=models.CharField(_('activation key'), max_length=40, null=True, blank=True)
    validated=models.BooleanField(default=False)
    

    I'd suggest adding a post_save signal to the Model, so that whenever a new ServiceHours instance is created (by saving the form), the email to the supervisor is sent.

    # Add this to your models file
    # Required imports 
    
    from django.db.models.signals import post_save
    from django.utils.hashcompat import sha_constructor
    import random
    
    def _create_and_send_activation_key(sender, instance, created, **kwargs):
        if created:    # Only do this for newly created instances.
            salt = sha_constructor(str(random.random())).hexdigest()[:5]        
            # Set activation key based on supervisor email 
            instance.activation_key = sha_constructor(salt+instance.supervisor_email).hexdigest()
            instance.save()
            # Create email
            subject = "Please validate"
            # In the message, you can use the data the volunteer has entered by accessing 
            # the instance properties
            message = "Include instance hours, volunteer's name etc\n"
            # Insert the activation key & link
            messsage += "Click here: %s" % (reverse("validate_hours", kwargs={'id': instance.id, 'activation_key':instance.activation_key})
    
            # Send the mail
            from django.core.mail import send_mail # Move this import to top of your file ofcourse, I've just put it here to show what module you need
            send_mail(subject, message, sender, recipients)
    
    post_save.connect(_create_and_send_activation_key, sender=ServiceHours)
    

    Define a view to validate service hours based on an activation key

      # in views.py
      def validate_hours(request, id, activation_key):
          # find the corresponding ServiceHours instance
          service_hours = ServiceHours.objects.get(id=id, activation_key=activation_key)
          service_hours.validated = True
          service_hours.save()
    

    In your urls.py, define an url to your validate_hours view:

    urlpatterns += patterns('',
        url(r'^validate-hours/(?P<id>[0-9]+)/(?P<activation_key>\w+)', validate_hours, name='validate_hours'),
    

    This has all been off the top of my head, so please excuse any errors. I hope you get the gist of the process and can extend according to your exact needs.