0

In my project I have two different types of users: teacher and student, each with their own profile data.

After searching for the best approach it seems the way to go forward is using multi-table inheritance:

class BaseProfile(models.Model):
    user = models.OneToOneField(User)
    profile = models.CharField (max_length=10, choices={'teacher', 'student'})
    # other common fields

class Teacher(BaseProfile):
    # teacher specific fields

class Student(BaseProfile):
    # student specific fields

And in settings.py: AUTH_PROFILE_MODULE = myapp.BaseProfile.

Now I want to implement the same functionalities as in django-profiles:

  • create profiles
  • edit profiles
  • display profiles

I have a good idea how to do the edit and display part when I have the correct value in the field profile of BaseProfile.

The problem:

Now I want the creation of the profile to be done automatically (and in the right db: Teacher or Student) directly when a user is created by using a signal. The field profile should contain the value "student" when the user registers through the site via the registration form. The value should be "teacher" when the admin creates a new user through the admin interface.

Anyone an idea how I can accomplish this? Probably I need to write a custom signal, something like the below, and send it from the User Model, but didn't found a working solution yet:

def create_user_profile(sender, instance, request, **kwargs):
    if request.user.is_staff:
        BaseProfile(user=instance, profile='teacher').save()
    else:
        BaseProfile(user=instance, profile='student').save()

Other and better approaches are of course also welcome!

Thanks!

Köver
  • 371
  • 4
  • 12
  • I'm not sure you can modify signal raised when User is saved. Other solution would be create appropriate profile when user is registered. – Rohan Jul 05 '12 at 05:04
  • Hi Rohan, thx for the input. In the following post this solution is also suggested: (http://stackoverflow.com/questions/3100521/django-registration-and-multiple-profiles). I'll give it a try. Thanks! – Köver Jul 05 '12 at 20:14

1 Answers1

1

In my opinion it isn't a good approach.

I would recommend doing 1 unified profile which will contain an option: user_type = models.CharField(choices=[your_choices], max_length=4)

Then in models you would create two forms - 1 for teacher and 1 for student.

class ProfileFOrm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(BaseProfileForm, self).__init__(*args, **kwargs)
        for name in self.fields:
            self.fields[name].required = True

class TeacherProfile(ProfileForm):
    class Meta:
        model = Profile
        fields = ('your_fields')


class StudentProfile(ProfileForm):
    class Meta:
        model = Profile
        fields = ('school')

That's just my idea for that :)


Edited

Profile edition:

view.

def profile(request):
p = get_objects_or_404(ProfileModel, user=request.user)
return TemplateResponse(request, 'template.html', {'profile': p})

In models we need a function to check if user is a student or a teacher, so:

class Profile(models.Model):
    ... your fields here...
    def get_student(self):
        return self.user_type == 1

In templates:

{% if profile.get_student%}

>>>>get all data for students ex: <<<<
{{profile.name}}

{% endif %}


{% if profile.get_teacher %}
....
Efrin
  • 2,323
  • 3
  • 25
  • 45
  • Hi Efrin, thx for the input. Indeed that is also a way to go, but it is (according to me) a less 'clean' solution and less flexible. I want to stick with the multi-table inheritance. Just need to find a way to fill in that one field `profile` in an automated way. – Köver Jul 05 '12 at 20:08
  • In my opinion its a bit cleaner way and later it will be way easier to maintain :) We used to have seperated profiles earlier in our project but at some point it was really annoying when we had to access a profile and grab some data. What if a student want's to become a teacher :)? It would be a bit annoying to create a new account in this matter. – Efrin Jul 05 '12 at 20:16
  • There you have a point :) So your approach is the following: use one 'general' profile model containing all the fields used in all the different profiles. And then you differentiate in profiles by making various 'profileforms'. Still have two more questions: 1. how do you display a certain profile? I guess you probably use different templates per profile? 2. How do you fill the user_type field? Is that field filled during the registration of a user? Thx! – Köver Jul 05 '12 at 20:38
  • To display a certain profile you would want to use only 1 view. check it in my post above( I'll edit it in a sec) – Efrin Jul 06 '12 at 03:51
  • Hi Efrin, thx for the insights. I implemented following solution: one 'complete' profile model and differentiate in forms and templates. Using this approach I can also fit everything in django-profiles. Regards! – Köver Jul 07 '12 at 08:50