I have a UserProfile model extending contrib.auth.User, and when I try to save it, the extra information I added in the profile is not saved.
Here is Models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name='profile')
cellphone = models.CharField(max_length=20, blank=True, default='')
def __str__(self):
return self.user.username
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created =
UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
And forms.py
class UserProfileForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
email = forms.EmailField(required=True)
cellphone = forms.CharField(max_length=20)
class Meta:
model = User
# fields = ('cellphone', )
fields = ('username', 'cellphone', 'email', 'password', )
And finally my view.py
def register(request):
form = UserProfileForm(request.POST or None)
if form.is_valid():
user = form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.profile.cellphone = form.cleaned_data['cellphone']
user.set_password(password)
user.save()
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return render(request, 'user/index.html', {'user': user})
else:
return render(request, 'user/register.html', {'form': form, })
I couldn't figure out why it is not saving the cellphone attribute.
Add user.profile.save() in view after user.profile.cellpone = ... line.
Related
Greeting,
I am trying to add to User form a new CharField named company but even when the field is filled the data are not saved... I tried the following with no success as I got the error in the title.
views.py
def register(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user_frm = form.save(commit = False)
user_frm.company = request.user.company
user_frm.save()
username = form.cleaned_data.get('username')
messages.success(request, f"Registration Complete! User: {username}")
username = form.cleaned_data.get('username')
login(request, user_frm)
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}:{form.error_messages[msg]}")
return render(request = request,
template_name = "main/register.html",
context={"form":form})
form = NewUserForm
return render(request,
"main/register.html",
context={"form":form})
forms.py
class NewUserForm(UserCreationForm):
email = forms.EmailField(required=True)
company = forms.CharField( max_length= 500)
class Meta:
model = User
fields = ("username", "email", "company", "password1", "password2")
def save(self, commit=True):
user = super(NewUserForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.company = self.cleaned_data["company"]
if commit:
user.save()
return user
Try this:
models.py
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
nickname = models.CharField("昵称", max_length=20, null=True, blank=True)
company = models.CharField(max_length=200, null=True, blank=True)
class Meta:
verbose_name = verbose_name_plural = "个人信息"
def __str__(self):
return self.nickname or self.user.username
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
"""创建user的同时自动创建profile并与之关联"""
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def save_user_profile(sender, instance, **kwargs):
"""保存user的同时也保存对应的profile"""
instance.profile.save()
views.py
def register(request):
form_class = NewUserForm
if request.method == "POST":
form = form_class(request.POST)
if form.is_valid():
user = form.save()
messages.success(request, f"Registration Complete! User: {user.username}")
login(request, user)
return redirect("main:homepage")
else:
form = form_class()
return render(request, "main/register.html", {"form":form})
forms.py
class NewUserForm(UserCreationForm):
email = forms.EmailField(required=True)
company = forms.CharField(max_length= 500)
def save(self, commit=True):
if not commit:
return super().save(commit=commit)
company = self.cleaned_data.pop("company", None)
user = super().save()
user.profile.company = company
user.profile.save()
return user
class Meta:
model = User
fields = ("username", "email", "company", "password1", "password2")
SOLVED using the following:
def update_user_data(user):
Profile_Reg.objects.update_or_create(user=user, defaults={'company': user.company,})
def register(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.company = form.cleaned_data.get('company')
update_user_data(user)
user.save()
raw_password = form.cleaned_data.get('password1')
username = form.cleaned_data.get('username')
messages.success(request, f"Registration Complete! User: {username}")
#breakpoint()
#user = authenticate(username=user.username, password=raw_password)
#breakpoint()
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}:{form.error_messages[msg]}")
return render(request = request,
template_name = "main/register.html",
context={"form":form})
form = NewUserForm
return render(request,
"main/register.html",
context={"form":form})
where Profile_Reg is a model:
class Profile_Reg(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.CharField(max_length=5000)
def __str__(self):
return str(self.user)
I wrote the following code which creates a new user and tries to create a profile for that user:
class RegisterForm(UserCreationForm):
email = forms.EmailField(max_length=200, help_text='Required')
class Meta:
model = CustomUser
fields = ('username', 'email', 'password1', 'password2')
#login_required(login_url="/login")
def index(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
profile = Profile().save()
user = form
user.profile = profile
user.save()
return redirect('users')
else:
print(form.errors)
else:
form = RegisterForm()
user_model = get_user_model()
users = user_model.objects.all()
paginator = Paginator(users, 15)
page = request.GET.get('page')
users = paginator.get_page(page)
return render(request, 'users/index.html', {'users': users, 'form': form})
class Profile(models.Model):
has_premium_until = models.DateTimeField(null=True, blank=True)
has_premium = models.BooleanField(default=False)
has_telegram_premium_until = models.DateTimeField(null=True, blank=True)
has_telegram_premium = models.BooleanField(default=False)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class CustomUser(AbstractUser):
email = models.EmailField(max_length=255, unique=True)
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, null=True)
When I'm submitting the form the user as well as the profile is created but the profile is not stored in the user (the profile_id stays null).
Anyone who can help me out?
Your user is actually just a reference to the ProfileForm you constructed. You can obtain the user that has logged in with request.user. So you can update the user with:
#login_required(login_url='/login')
def index(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
profile = Profile().save()
user = request.user
user.profile = profile
user.save()
return redirect('users')
else:
print(form.errors)
else:
form = RegisterForm()
# …
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))
Upon signup, I'd like to request the user for:
Full name (I want to save it as first and last name though)
Company name
Email
Password
I've read through dozens of similar situations on StackOverflow. In models.py, I extend the User model like so:
# models.py
class UserProfile(models.Model):
company = models.CharField(max_length = 50)
user = models.OneToOneField(User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
Source: Extending the User model with custom fields in Django
I've also added:
# models.py
class SignupForm(UserCreationForm):
fullname = forms.CharField(label = "Full name")
company = forms.CharField(max_length = 50)
email = forms.EmailField(label = "Email")
password = forms.CharField(widget = forms.PasswordInput)
class Meta:
model = User
fields = ("fullname", "company", "email", "password")
def save(self, commit=True):
user = super(SignupForm, self).save(commit=False)
first_name, last_name = self.cleaned_data["fullname"].split()
user.first_name = first_name
user.last_name = last_name
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
And in views.py:
# views.py
#csrf_exempt
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
new_user = form.save()
first_name, last_name = request.POST['fullname'].split()
email = request.POST['email']
company = request.POST['company'],
new_user = authenticate(
username = email,
password = request.POST['password']
)
# Log the user in automatically.
login(request, new_user)
Right now, it doesn't store the company name. How do I do that?
user_profile = new_user.get_profile()
user_profile.company = company
user_profile.save()
Don't forget to configure your UserProfile class in settings so Django knows what to return on user.get_profile()