I'm using django-registration in my application. I want to create different kinds of users with different profiles. For example, one user is a teacher and another user is a student.
How can I modify registration to set the user_type and create the right profile?
Long answer :p
I've found The Missing Manual post invaluable for this kind of problem as it explains many of features of the django-profiles and django-registration systems.
I'd suggest using multi table inheritance on the single profile you're allowed to set via the AUTH_PROFILE_MODULE
For instance
#models.py
class Profile(models.Model):
#add any common fields here (first_name, last_name and email come from User)
#perhaps add is_student or is_teacher properites here
@property
def is_student(self):
try:
self.student
return True
except Student.DoesNotExist:
return False
class Teacher(Profile):
#teacher fields
class Student(Profile):
#student fields
django-registration uses signals to notify you of a registration. You should be creating the profile at that point so you are confident that calls to user.get_profile() will always return a profile. The signal code used is
#registration.signals.py
user_registered = Signal(providing_args=["user", "request"])
Which means when handling that signal you have access to the request made. So when you POST the registration form include a field that identifies what type of user to create.
#signals.py (in your project)
user_registered.connect(create_profile)
def create_profile(sender, instance, request, **kwargs):
from myapp.models import Profile, Teacher, Student
try:
user_type = request.POST['usertype'].lower()
if user_type == "teacher": #user .lower for case insensitive comparison
Teacher(user = instance).save()
elif user_type == "student":
Student(user = instance).save()
else:
Profile(user = instance).save() #Default create - might want to raise error instead
except KeyError:
Profile(user = instance).save() #Default create just a profile
If you want to add anything to the model that is created, that isn't covered by default field values, at registration time you can obviously pull that from the request.
http://docs.djangoproject.com/en/1.2/topics/auth/#groups
Django groups are a great way to define what you are looking for. You can have one User extended profile that will contain all attributes of teachers and students.
class MasterProfile(models.Model):
user = models.ForeignKey(User, unique=True)
# add all the fields here
Then define groups: teacher
and student
and you associate each MasterProfile to either a teacher or a student.
Django Group table can help you define your various roles and allocate users to groups correctly.
I had the same issue and I tried the answer suggested by Chris, however it didn't work for me.
I'm only a newbie in Django, but I think the args taken by handler create_profile
should match those under providing_args
by signal user_registered
, and in Chris's answer they don't (I think they probably match those passed by signal post_save
, which I've seen used in the Missing Manual that he quotes)
I modified his code to make args match:
def create_profile(sender, **kwargs):
"""When user is registered also create a matching profile."""
request, instance = kwargs['request'], kwargs['user']
# parse request form to see whether profile is student or teacher
try:
user_type = request.POST['usertype'].lower()
print(user_type)
if user_type == "teacher": #user .lower for case insensitive comparison
Teacher(user = instance).save()
elif user_type == "student":
Student(user = instance).save()
else:
Userprofile(user = instance).save() #Default create - might want to raise error instead
except KeyError:
Userprofile(user = instance).save() #Default create just a profile
and seems to be working now
来源:https://stackoverflow.com/questions/3100521/django-registration-and-multiple-profiles