Django registration and multiple profiles

元气小坏坏 提交于 2019-11-28 17:20:16

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.

xuloChavez

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!