djangodjango-modelsdjango-formsdjango-usersdjango-profiles

django profile creation, set User profile while using multiple profile types


I am stuck at user registration, I actually intends to have different profile types. While registration I am unable to set UserProfile while creating a user. I am using UserCreationForm. code in my files are as following.

from django.contrib.auth.forms import UserCreationForm
from registration.forms import RegistrationForm
from django import forms
from django.contrib.auth.models import User
from accounts.models import UserProfile
from django.utils.translation import ugettext_lazy as _
from person.models import Person
from pprint import pprint


class UserRegistrationForm(UserCreationForm):
    #email = forms.EmailField(label = "Email")
    fullname = forms.CharField(label = "Full name")

    class Meta:
        model = User
        fields = ("email","fullname","password1","password2" )

    def __init__(self, *args, **kwargs):
        super(UserRegistrationForm, self).__init__(*args, **kwargs)
        del self.fields['username']

    def clean_email(self):
        """
        Validate that the supplied email address is unique for the
        site.

        """
        if User.objects.filter(email__iexact=self.cleaned_data['email']):
            raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
        return self.cleaned_data['email']

    def save(self, commit=True):
        user = super(UserRegistrationForm, self).save(commit=False)
        #user_profile=user.set_profile(profile_type="Person")

        UserProfile.profile.person.full_name = self.cleaned_data["fullname"]
        user.email = self.cleaned_data["email"]
        if commit:
            user.save()
        return user

class CompanyRegistrationForm(UserCreationForm):
    email=forms.EmailField(label="Email")

class UserProfileForm(forms.ModelForm):
    class Meta:
        model=UserProfile
        exclude=('user',)

accounts/models.py

    from django.db import models
from django.contrib.auth.models import User


class UserProfile(models.Model):
    user=models.OneToOneField(User) 
    meta_keywords=models.CharField("Meta Keywords",max_length=255,
            help_text="Comma delimited set of keywords of meta tag")
    meta_description=models.CharField("Meta Description",max_length=255,
            help_text='Content for description meta tag')

    def __unicode__(self):
        return "User Profile for: "+self.username

    class Meta:
        ordering=['-id']

views.py

    from django.contrib.auth.forms import UserCreationForm
from django.template import RequestContext
from django.shortcuts import render_to_response,get_object_or_404
from django.core import urlresolvers
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from accounts.forms import UserRegistrationForm, UserProfileForm
#from accounts.forms import UserProfile

def register(request,template_name="account/register.html"):
    if request.method=='POST':
        postdata=request.POST.copy()
        form=UserRegistrationForm(postdata)
        user_profile=UserProfileForm(postdata)
        if form.is_valid():
            form.save()
            un=postdata.get('username','')
            pw=postdata.get('password','')
            from django.contrib.auth import login,authenticate
            new_user=authenticate(username=un,password=pw)
            if new_user and new_user.is_active:
                login(request,new_user)
                url=urlresolvers.reverse('dashboard')
                return HttpResponseRedirect(url)     
    else:
        form=UserRegistrationForm()
    page_title="User Registration"
    return render_to_response(template_name,locals(),context_instance=RequestContext(request))


@login_required
def dashboard(request):
    pass

@login_required
def settings(request):
    pass

As I am using multiple profiles so following is code of one of those profiles' models.py:

    from django.db import models
from django.contrib.auth.models import User
from accounts.models import UserProfile

class Person(UserProfile):
    skills=models.CharField(max_length=100)
    fullname=models.CharField(max_length=50)
    short_description=models.CharField(max_length=255)
    is_online=models.BooleanField(default=False)
    tags=models.CharField(max_length=50)
    profile_pic=models.ImageField(upload_to="person_profile_images/")
    profile_url=models.URLField()
    date_of_birth=models.DateField()
    is_student=models.BooleanField(default=False)
    current_designation=models.CharField(max_length=50)
    is_active_jobseeker=models.BooleanField(default=True)
    current_education=models.BooleanField(default=True)


    class Meta:
        db_table='person'

My profile auth in settings.py

AUTH_PROFILE_MODULE='accounts.UserProfile'

Here is a file that also I used after looking at some other place, profile.py: from accounts.models import UserProfile from accounts.forms import UserProfileForm from person.models import Person from company.models import Company

def retrieve(request,profile_type):
    try:
        profile=request.user.get_profile()
    except UserProfile.DoesNotExist:
        if profile_type=='Person':
            profile=Person.objects.create(user=request.user)
        else:
            profile=Company.objects.create(user=request.user)
        profile.save()
    return profile

def set(request,profile_type):
    profile=retrieve(request,profile_type)
    profile_form=UserProfileForm(request.POST,instance=profile)
    profile_form.save()

I am new and confuse, have seen documentation also. Also saw other solutions at stackoverflow.com but didn't find any solution of my problem. So please tell if you find anything helpful for me. It doesn't seems to be a big problem but as I am new to it so it is a problem for me.


Solution

  • Multiple profile types won't work with the OneToOne relation that is required by Django profile mechanism. I suggest you keep a single profile class containing data common to all profile types and you store type-specific data in a separate set of classes that you link to your profile class using a generic relation.

    EDIT:

    Thanks for the clarification. Looking at your code again today it seems that you might indeed be able to accomplish what your trying to do with model inheritance. I think the problem is in the save() method of UserRegistrationForm. Try something like this:

    def save(self, commit=True):
        user = super(UserRegistrationForm, self).save(commit=False)
        user.email = self.cleaned_data["email"]
        if commit:
            user.save()
            person = Person(user=user)
            person.full_name = self.cleaned_data["fullname"]
            person.save()
        return user