Reputation: 39
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
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
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