I'm trying to add more fields to Django's default User model. I'm using the OneToOneField method. I want to create a signup page that allows the user to fill out a username, password, email, and other fields that I will add into a separate Profile model.
I've used some code snippets I've found and tried to make it work. However, I keep getting an IntegrityError at /account/signup/
UNIQUE constraint failed: accounts_profile.user_id error.
I think the problem is that right when the User gets created, a Profile gets created as well. Then When A new Profile gets created using the User's primary key it gives an error because a Profile for that primary key already exists.
Can someone show me the correct way to do this?
Here's all the relevant code:
models.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
GENDER_CHOICES = (
('MALE', 'Male'),
('FEMALE', 'Female')
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
middle_name = models.CharField(max_length=30, blank=True, default='')
prefix = models.CharField(max_length=6, blank=True, default='')
suffix = models.CharField(max_length=10, blank=True, default='')
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
forms.py
from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = (
'middle_name',
'prefix',
'suffix',
)
def save(self, commit=True):
profile = super(ProfileForm, self).save(commit=False)
profile.middle_name = self.cleaned_data['middle_name']
profile.prefix = self.cleaned_data['prefix']
profile.suffix = self.cleaned_data['suffix']
if commit:
profile.save()
return profile
views.py
...
def signup_view(request):
if request.method == 'POST':
register = RegistrationForm(request.POST, prefix='register')
userprofile = ProfileForm(request.POST, prefix='profile')
print(register.is_valid())
print(userprofile.is_valid())
if register.is_valid() * userprofile.is_valid():
user = register.save()
profile = userprofile.save(commit=False)
print(user)
profile.user = user
profile.save()
return HttpResponse('congrats')
else:
return HttpResponse('errors')
else:
userform = RegistrationForm(prefix='register')
userprofileform = ProfileForm(prefix='profile')
return render(request, 'accounts/signup.html', {'userform': userform,
'userprofileform': userprofileform})
Related
first post here. Im trying to query the user so i from the form so i can save the user in my database.
This is my code
form = lageBruker(request.POST)
bruker = User.objects.create(format(request.POST['username']))
print()
if request.method == 'POST':
if form.is_valid():
fornavn = request.POST['first_name']
etternavn = request.POST['last_name']
email = request.POST['email']
kunde = Kunde.objects.create(
#bruker = bruker,
fornavn=fornavn,
etternavn=etternavn,
email=email
)
kunde.save()
context = {'form': form}
return render(request, 'ebutikk/registrer.html', context)
Kunde Model:
class Kunde(models.Model):
bruker = models.OneToOneField(
User, null=True, blank=True, on_delete=models.CASCADE)
fornavn = models.CharField(max_length=200, null=True, blank=True)
etternavn = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.etternavn
What im trying to do is, when the registration form is submittet, i want to save the registerd user as a kunde/customer. I dont have a User model, i use the default made by django with the import:
from django.contrib.auth.models import User
I make the form by importing the user creation form given by django and customizing it im my forms.py file.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class lageBruker(UserCreationForm):
class Meta:
model = User
fields = ['username',
'email',
'first_name',
'last_name',
'password1',
'password2']
Normally, you'd simply create the Kunde model like this:
class Kunde(models.Model):
bruker = models.OneToOneField(
User, null=True, blank=True, on_delete=models.CASCADE)
# more fields here, so the model makes sense
#property
def fornavn(self): return self.user.first_name
#property
def etternavn(self): return self.user.last_name
#property
def email(self): return self.user.email
Then all you need to do is:
def customer_signup_view(self, request):
if request.method == "POST":
form = lageBruker(request.POST)
# Saving the model form returns the user created
user = form.save()
# Now use that user to create a new customer
Kunde.objects.create(user=user)
return redirect("success/")
return render(request, 'ebutikk/registrer.html', {"form": lageBruker())
I'm trying to write a REST API using Django and DRF. I'm trying to create a user model and use it in my application. But the problem is that it returns a 400 error status code which says:
{"username":["This field is required."]}
This is my code for models:
import uuid
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
from django.dispatch import receiver
from django.utils.encoding import python_2_unicode_compatible
from django.db.models.signals import post_save
from rest_framework.authtoken.models import Token
from api.fileupload.models import File
#python_2_unicode_compatible
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField('Email address', unique=True)
name = models.CharField('Name', default='', max_length=255)
phone_no = models.CharField('Phone Number', max_length=255, unique=True)
address = models.CharField('Address', default='', max_length=255)
country = models.CharField('Country', default='', max_length=255)
pincode = models.CharField('Pincode', default='', max_length=255)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
The Serializer:
class CreateUserSerializer(serializers.ModelSerializer):
username = None
def create(self, validated_data):
validated_data['username'] = uuid.uuid4()
user = User.objects.create_user(**validated_data)
return user
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.address = validated_data.get('address', instance.address)
instance.country = validated_data.get('country', instance.country)
instance.pincode = validated_data.get('pincode', instance.pincode)
instance.phone_no = validated_data.get('phone_no', instance.phone_no)
instance.email = validated_data.get('email', instance.email)
instance.save()
return instance
class Meta:
unique_together = ('email',)
model = User
fields = (
'id', 'password', 'email', 'name', 'phone_no', 'address', 'country', 'pincode',
)
extra_kwargs = {'password': {'write_only': True}}
Admin.py file:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
#admin.register(User)
class UserAdmin(UserAdmin):
pass
class User(AbstractUser):
As your User model inherits from AbstractUser, it will inherit
the username field.
Just remove the username field from your User model by setting username = None like this:
class User(AbstractUser):
# ...
username = None
# ...
class UserAdmin(UserAdmin):
As your UserAdmin model inherits from django.contrib.auth.admin.UserAdmin, you will need to update fieldsets, list_display, search_fields, and ordering fields in your UserAdmin model because they use username which you have removed from your User model.
Abstract User always has the username field. Removing it will cause problems. I will suggest you store the email address of the user in username field as well and use that. Please make sure its always updated in both fields which is not very hard.
I am trying to make a webapp that includes register/login operations. The login is working fine but the registration form is frustrating.
I have a class registration form that inherits from UserCreationForm. The users are created and seen in the admin page when created but the problem I am having is not being able to see them in my UserProfile model in the admin page. It does not link the information and I could not find a way the link them.
Here is the registration form:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
city = forms.CharField(required=False)
country = forms.CharField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
username = forms.CharField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'country',
'city',
'email'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
#user.first_name = self.cleaned_data['first_name']
if commit:
user.save()
return user
Here are my models:
class UserProfile(models.Model):
user = models.OneToOneField( User,
on_delete=models.CASCADE
)
username = models.TextField(max_length=30, default="")
first_name = models.TextField(max_length=30, default="")
last_name = models.TextField(max_length=30, default="")
country = models.TextField(max_length=30, default="Which country are you from?")
city = models.TextField(max_length=30, default="Which city are you from?")
class ColorChoice(models.Model):
user = models.ForeignKey(
'UserProfile',
on_delete=models.CASCADE
)
color1 = models.IntegerField()
color2 = models.IntegerField()
color3 = models.IntegerField()
color4 = models.IntegerField()
color5 = models.IntegerField()
and my view.py that does the registering:
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('color')
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'account/create_new.html', args)
Your form is only creating a new objects for User. You would need to add a signal for example to create a new object for UserProfile.
Something like this:
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
signals.post_save.connect(create_user_profile, sender=User)
Hi i need add request user pk to UserCreationForm. I try many times, but with out results. In my dashboard i have user owner and i have user seller.
One model for all 3 types user. So Owner can create another user with role=seller, but for this i need add parent field with param=request.user.pk to seller
Custom UserModel
from django.db import models
from django.contrib.auth.models import AbstractUser
USER = 0
OWNER = 1
SELLER = 2
user_type_choice = (
(USER, 'User'),
(OWNER, 'Owner'),
(SELLER, 'Seller'),
)
class User(AbstractUser):
role = models.CharField(max_length=100, choices=user_type_choice, default=USER)
idn = models.CharField(max_length=10, blank=True, default=None, null=True)
mobile = models.CharField(max_length=15, blank=True, default=None, null=True)
parent = models.ForeignKey('self', null=True, blank=True)
tariff = models.IntegerField(default=None, null=True, blank=True)
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
forms.py
class SellerRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2') """try add and remove 'parent' here in felds """
def save(self, commit=True):
user = super(SellerRegisterForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.role = ROLE_SELLER
# try add user.parent = self.request.user.pk
# but it does not work
if commit:
user.save()
return user
views.py
def register_seller(request):
if request.method == 'POST':
form = SellerRegisterForm(request.POST) # create form object
if form.is_valid():
#try add new_form = form.save(commit=False)
# new_form.parent = request.user.pk
# new_form.save() but it not working
form.save()
return HttpResponseRedirect('/accounts/login')
else:
form = SellerRegisterForm()
return render(request, 'register_owner.html', {'form': form})
You need to pass the user object through the form's __init__ method.
class SellerRegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(SellerRegisterForm, self).__init__(*args, **kwargs)
and in your view:
form = SellerRegisterForm(request.POST, user=request.user)
Then simply use self.user anywhere in your form class.
I am very new to Django and I am trying to create a registration form. This is the relevant part of my model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
university = models.ForeignKey('University')
course_title = models.ForeignKey('Course_Title')
class Meta:
db_table = 'user_profile'
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
This is the form I am using:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from shelf.models import University, Course_Title, UserProfile
class RegistrationForm(UserCreationForm):
error_messages = {
'duplicate_email': "A user with that e-mail already exists.",
'email_mismatch': "The two e-mail fields didn't match.",
}
# An e-mail is being used instead of the usual Django username.
username = forms.EmailField(label="E-mail")
username2 = forms.EmailField(label="Confirm E-mail")
university = forms.ModelChoiceField(queryset=University.objects.all(), empty_label="Please choose a university")
course_title = forms.ModelChoiceField(queryset=Course_Title.objects.all(), empty_label="Please choose a course title")
class Meta:
model = User
fields = ("first_name", "last_name", "university", "course_title", "username", "username2")
.
.
.
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.save()
user_profile = UserProfile(user=user, university=self.cleaned_data["university"], course_title=self.cleaned_data["course_title"])
if commit:
user_profile.save()
return user_profile
And, this is my view:
def index(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/")
else:
form = RegistrationForm()
return render(request, "shelf/register.html", {'form': form, })
I get the error user_profile.university_id may not be NULL. I have looked a lot for why this happens and I understand why it happens. But I can't seem to fix it.
Thanks in advance.
It looks like the problem is caused by your signal handler:
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance) # no university here
post_save.connect(create_user_profile, sender=User)
Please try disable this handler and test again.
If you want the signal handler, please try changing the form.save method:
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False) #this should trigger the signal handler to create a UserProfile instance, but not commit
user_profile = user.get_profile()
user_profile.university=self.cleaned_data["university"]
user_profile.course_title=self.cleaned_data["course_title"]
if commit:
user.save()
user_profile.save()
Be careful, if you create a user in the shell, you still get the same error, I think maybe you could add default value for university and course_title field in UserProfile model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
university = models.ForeignKey('University', default=1)
course_title = models.ForeignKey('Course_Title', default=1)
I've the same issue but couldn't solve it though I followed the steps
Model
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
url = models.URLField()
home_address = models.TextField()
user = models.ForeignKey(User, unique=True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
View
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User, Group
from django import forms
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.template.context import RequestContext
from django.views.decorators.csrf import csrf_protect
class RegisterForm(UserCreationForm):
permission_choices = (
('1', 'test1'),
('2', 'test2'),
)
email = forms.EmailField(required=False)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
url = forms.URLField()
permission = forms.ChoiceField(choices=permission_choices)
class Meta(UserCreationForm.Meta):
model = User
fields = ('first_name', 'last_name', 'url', 'username', 'email', 'password1', 'password2', 'permission')
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
user_profile = user.get_profile()
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.permission = self.cleaned_data['permission']
user_profile.url = self.cleaned_data['url']
if commit:
user.save()
user_profile.save()
return user
#csrf_protect
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
new_user = form.save()
if new_user.permission == 'q':
try:
new_user.groups.add(Group.objects.get(name='test1'))
except Group.DoesNotExist:
u = User.objects.get(pk=new_user.pk)
u.delete()
return HttpResponse('The Organisation you\'ve just choosed doesn\' exist')
return HttpResponse('OK')
else:
form = RegisterForm()
return render_to_response('registration/user.html', {'form': form}, context_instance=RequestContext(request))