Pratirup Mukherjee
Pratirup Mukherjee

Reputation: 39

Django create user profile at the time of registration from submission

I am working on a Role Based Access Control system on django.where at the signup/register people will be designated to a 'department' and will be assigned a 'role' Hence I created a custom user model

models.py

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver


 class Profile(models.Model):

 DEPARTMENT_CHOICES = (
    ('Production', 'Production'),
    ('Marketing', 'Marketing'),
    ('IT', 'IT'),
    ('HR', 'HR'),
    ('Accounts', 'Accounts'),
)
ROLE_CHOICES = (
    ('Manager', 'Manager'),
    ('Team Lead', 'Team Lead'),
    ('Member', 'Member'),
)

user = models.OneToOneField(
    User,)
department = models.CharField(
    max_length=50, choices=DEPARTMENT_CHOICES, null=True)
role = models.CharField(max_length=50, choices=ROLE_CHOICES, null=True)

def __unicode__(self):
    return unicode(self.user.first_name + ' ' + self.user.last_name)

def __str__(self):
    return self.user.first_name + ' ' + self.user.last_name


def create_profile(sender, **kwargs):
    if kwargs['created']:
    user_profile = Profile.objects.create(user=kwargs['instance'])
    pass

post_save.connect(create_profile, sender=User)

Then i created a form like

forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Profile


class SignUpForm(UserCreationForm):
DEPARTMENT_CHOICES = (
    ('Production', 'Production'),
    ('Marketing', 'Marketing'),
    ('IT', 'IT'),
    ('HR', 'HR'),
    ('Accounts', 'Accounts'),
)
ROLE_CHOICES = (
    ('Manager', 'Manager'),
    ('Team Lead', 'Team Lead'),
    ('Member', 'Member'),
)
first_name = forms.CharField(
    max_length=30, required=True, help_text='Optional.')
last_name = forms.CharField(
    max_length=30, required=True, help_text='Optional.')
email = forms.EmailField(
    max_length=254, required=False)
department = forms.ChoiceField(choices=DEPARTMENT_CHOICES, )
role = forms.ChoiceField(choices=ROLE_CHOICES, )

class Meta:
    model = User
    fields = ('first_name', 'last_name', 'username',
              'email', 'password1', 'password2', 'department', 'role')

The my views

from django.shortcuts import render, redirect, render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
from .forms import SignUpForm
from .models import Profile
from django.shortcuts import get_object_or_404
from django.http import Http404
from django.contrib.auth.models import User
from django.template import RequestContext

def register(request):
if request.user.is_authenticated:
    if request.user.is_superuser or request.user.role == 'Manager':
        if request.method == 'POST':
            form = SignUpForm(request.POST)
            if form.is_valid():
                user = form.save()
                userprofile = Profile.objects.update(
                    user=user, department=form.cleaned_data['department'])
                userprofile = Profile.objects.update(
                    user=user, role=form.cleaned_data['role'])
        else:
            form = SignUpForm()

        c = {
            'form': form,
        }

        return render(request, 'registration/register.html', c)
    else:
        raise Http404
else:
    raise Http404

my register.html

{% extends 'layouts/base.html' %} {% load widget_tweaks %}{% block additionalbottom %}
<script>
var allParas = document.getElementsByTagName('div');
//filter by class name if desired...
for (var i = 0; i < allParas.length; i++) {
    if (allParas[i].getElementsByTagName('*').length == 0) {
        allParas[i].style.display = 'none';
    }
}
</script>
{% endblock %} {% block content %}
<div class="login-page">
    <div class="form">
        <h2>User Registration</h2>
        <form class="login-form" method="post">
            {% csrf_token %}
            <div class="row">
                {% endblock %} {% for field in form %}
                <div class="col-md-6">
                    {% if field.name == "first_name" or field.name == "last_name" %} {% render_field field class="form-control" placeholder=field.label.capitalize %} {% endif %}
                </div>
                <div class="col-md-6">
                    {% if field.name == "username" or field.name == "email" %} {% render_field field class="form-control" placeholder=field.label.capitalize %} {% endif %}
                </div>
                <div class="col-md-6 form-group">
                    {% if field.name == "department" or field.name == "role" %} {% render_field field class="form-control" placeholder=field.label.capitalize %} {% endif %}
            </div>
            <div class="col-md-12">
                {% if field.name == "password1" %} {% render_field field class="form-control" placeholder=field.label.capitalize %} {% endif %}
            </div>
            <div class="col-md-12">
                {% if field.name == "password2" %} {% render_field field class="form-control" placeholder=field.label.capitalize %} {% endif %}
            </div>
            {% endfor %}
        </div>
        <div class="form-group">
            <button type="submit">Register</button>
        </div>
    </form>
    {% if form.errors %} {% for field in form %} {% for error in field.errors %}
    <div class="alert alert-danger">
        <strong>{{ error|escape }}</strong>
    </div>
    {% endfor %} {% endfor %} {% for error in form.non_field_errors %}
    <div class="alert alert-danger">
        <strong>{{ error|escape }}</strong>
    </div>
    {% endfor %} {% endif %}
</div>

now when ever i try to submit my form it says

IntegrityError at /register/ column user_id is not unique

i tried so many solutions from google and SO nothing seems to solve the problem can anyone tell me how to fix it or why it cannot be done if it cannot be done what is the work around

Upvotes: 1

Views: 3064

Answers (2)

Clement Tong
Clement Tong

Reputation: 46

This post helped me so much. For me, my issue was I used:

current_user = request.user when it should have been: current_user = form.save()

Upvotes: 0

H&#229;ken Lid
H&#229;ken Lid

Reputation: 23064

This is your problem.

Profile.objects.update(user=user, department=form.cleaned_data['department'])

This will attempt to update all profiles with the same data. If you have more than one Profile, that's not allowed, since user is a one-to-one relation.

I guess what you want to do is to create a new profile object instead. Try something like this:

Profile.objects.create(
    user=user,
    department=form.cleaned_data['department'], 
    role=form.cleaned_data['role'],
)

If you use a signal to create the Profile when you save a new User, you can use update_or_create instead.

Profile.objects.update_or_create(
    user=user,
    defaults={
        "department": form.cleaned_data['department'], 
        "role": form.cleaned_data['role'],
    }
)

Upvotes: 1

Related Questions