Wednesday, February 25, 2015

Auto create and populate UserProfile in Django 1.7 with django-auth-ldap

To map some extra information of the Active Directory user into my Django's StudentProfile (UserProfile) model (Django 1.7 and django-auth-ldap 1.2.5), I have to call a post_save signal:

In my models.py:

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django_auth_ldap.backend import LDAPBackend


class StudentProfile(models.Model):
user = models.OneToOneField(User, related_name="student_profile", related_query_name="profile")
student_number = models.CharField(max_length=255) # Office
class_of = models.CharField(max_length=255) # Description

def create_student_profile(sender, instance, created, **kwargs):
if created:
new_profile = StudentProfile.objects.create(user=instance)
user = LDAPBackend().populate_user(instance.username)
if user:
desc = user.ldap_user.attrs.get("description", [])[0]
office = user.ldap_user.attrs.get("physicalDeliveryOfficeName", [])[0]
new_profile.student_number = office
new_profile.class_of = desc
new_profile.save()

post_save.connect(create_student_profile, sender=User)


The first time a user log in, an User object will be created along with a StudentProfile object with data initialized from the ldap_user.

This process of mapping UserProfile attribute from LDAP has become complicated like this because Django 1.7 does not support UserProfile (the way I did is just a OneToOne mapping between two models) and django_auth_ldap won't honor any profile-related configuration. So, the only way to automatically generate userprofile from Active Directory is to populate the UserProfile with a post_save signal.


References:
[0] https://pythonhosted.org/django-auth-ldap/users.html#updating-users
[1] https://bitbucket.org/psagers/django-auth-ldap/src/4fc4bada7de5?at=1.2.5
[2] http://stackoverflow.com/questions/20613315/get-rid-of-get-profile-in-a-migration-to-django-1-6
[3] http://stackoverflow.com/questions/10284760/setting-up-django-auth-ldap-to-populate-user-profile
[4] https://docs.djangoproject.com/en/1.7/topics/auth/customizing/
[5] https://docs.djangoproject.com/en/1.7/ref/signals/#django.db.models.signals.post_save