Django ModelForm not retrieving field's value - python

I'm using two ModelForms to create na user with a Profile instance. Profile ModelForm has a single field. I'm doing form.save(commit=False), setting the required field (country) other than the one in the form and saving. I get an error saying that 'country_id' cannot be null.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
email_confirmed = models.BooleanField(default=False)
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
forms.py
class UserRegisterForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class ProfileRegisterForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['country']
views.py
def register(request):
if request.method == 'POST':
user_form = UserRegisterForm(request.POST)
profile_form = ProfileRegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.is_active = False
profile = profile_form.save(commit=False)
profile.user = user
user.save()
current_site = get_current_site(request)
subject = 'Activate Your Account'
message = render_to_string('account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': account_activation_token.make_token(user)
})
user.email_user(subject, message)
return redirect('activation_email_sent')
else:
user_form = UserRegisterForm()
profile_form = ProfileRegisterForm()
return render(request, 'register.html', {'user_form': user_form, 'profile_form': profile_form})

Yeah. I removed the post_save, made country nullable and saved user and profile separately. Thanks for the help.
views.py
def register(request):
if request.method == 'POST':
user_form = UserRegisterForm(request.POST)
profile_form = ProfileRegisterForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
user.is_active = False
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()

Related

NOT NULL constraint failed: home_profile.user_id

I have written an extension of the Django auth.user model which adds middle_name and phone fields to the model.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
middle_name = models.CharField(max_length=20, blank=True)
phone = models.CharField(max_length=10, blank=True)
def __str__(self):
return(f'{self.user.username} profile')
I am using the following forms to accept input from the user.
class RegistrationForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['first_name', 'last_name', 'email', 'username', 'password1', 'password2']
class ProfileForm(forms.ModelForm):
phone = forms.CharField(max_length=10, min_length=10)
middle_name = forms.CharField(max_length=20, required=True)
class Meta:
model = Profile
fields = ['middle_name', 'phone']
The view for the register route is as follows:
def register(request):
if request.method == 'POST':
user_form = RegistrationForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
username = user_form.cleaned_data.get('username')
user_form.save()
profile_form.save()
messages.success(request, f'Welcome { username }! Your account has been created. Sign in to continue.')
return redirect('login')
else:
return render(request, 'home/register.html', { 'user_form': user_form, 'profile_form': profile_form })
else:
user_form = RegistrationForm()
profile_form = ProfileForm()
return render(request, 'home/register.html', { 'user_form': user_form, 'profile_form': profile_form })
This is contents of the signals.py file
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
The issue is while a row for the user is getting created in the Profile model, data is not getting written into the fields of the row. I am seeing a Exception Value: NOT NULL constraint failed: home_profile.user_id
By using a signal, you will create a Profile object, but the profile_form will be unaware of that, and thus create another one that does not link to the user. You thus might want to remove the signals. Signals are often an anti-pattern, and furthermore there are several ORM calls that can circumvent the signals.
If you remove the signals, you will still need to link the Profile object wrapped in your profile_form to the user, you do this with:
# remove the signal that constructs a Profile
def register(request):
if request.method == 'POST':
user_form = RegistrationForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save() # ← assign the user to a variable
profile_form.instance.user = user # ← set it as user of the profile
profile_form.save()
messages.success(request, f'Welcome {user.username}! Your account has been created. Sign in to continue.')
return redirect('login')
else:
user_form = RegistrationForm()
profile_form = ProfileForm()
return render(request, 'home/register.html', { 'user_form': user_form, 'profile_form': profile_form })

Populate OneToOneField after submitting form Django

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()
# …

Why if I delete username field in django forms.ModelForm, registration fails?

I have a working example of a registration with username & email. I want to make it email only. When I start to manipulate it (ex. delete "username" in class UserForm (forms.py), I get IntegrityError at /application/register/ UNIQUE constraint failed: auth_user.username). How can I fix this?
models.py
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# additional
portfolio_site = models.URLField(blank=True)
profile_pic = models.ImageField(upload_to="profile_pics", blank=True)
def __str__(self):
return self.user.username
forms.py
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ("username", "email", "password")
class UserProfileInfoForm(forms.ModelForm):
class Meta():
model = UserProfileInfo
fields = ("portfolio_site","profile_pic" )
views.py
def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(data=request.POST)
profile_form = UserProfileInfoForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if "profile_pic" in request.FILES:
profile.profile_pic = request.FILES["profile_pic"]
profile.save()
registered = True
else:
print(user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileInfoForm()
return render(request, 'application/register.html', {
"user_form":user_form,
"profile_form":profile_form,
"registered":registered})

disable logout after adding user django

I need to create admin panel in django , admin will be able to add students"which extended from users " , I finally be able to add them , but after that I get "'AnonymousUser' object has no attribute '_meta'
User is added to the database correctly , But django logged me out !
How Can I keep my current user session !
class student(models.Model):
Computers = 1
Communications = 2
Dep_CHOICES = (
(Computers, 'Computers'),
(Communications, 'Communications'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
dep = models.PositiveSmallIntegerField(choices=Dep_CHOICES, null=True, blank=True)
deg = models.FloatField(null=True, blank=True)
def __str__(self): # __unicode__ for Python 2
return self.user.username
def create_user_profile(sender, instance, created):
if created:
student.objects.create(user=instance)
def save_user_profile(sender, instance , **kwargs):
instance.student.save()
class UserForm(ModelForm):
class Meta:
model = User
fields = ('username', 'email', 'password')
class studentForm(ModelForm):
class Meta:
model = student
fields = ('dep', 'deg')
The view
def add_stu(request):
if request.method == 'GET':
return render(request, "add_student.html")
else:
user_form = UserForm(request.POST, instance=request.user)
profile_form = studentForm(request.POST, instance=request.user.student)
user_form.save()
profile_form.save()
you can't save profile_form directly as it has a foreign key relation to user and is required. so before you can save profile_form you need to save user and then add the user to profile.
def add_stu(request):
if request.method == 'GET':
return render(request, "add_student.html")
else:
user_form = UserForm(request.POST)
profile_form = studentForm(request.POST)
new_user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = new_user
profile.save()

Django unable to encrypt user password info and unable to retrieve userprofile information

I have a web application which has user registration and update user profile. I am using password hashers.
This is my models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_images', blank=True)
def __unicode__(self):
return self.user.username
This is my forms.py
class UserForm(forms.ModelForm):
username = forms.CharField(
max_length=254,
widget=forms.TextInput(attrs={'class': "form-control input-lg",'placeholder': 'username'}),
)
email = forms.CharField(
max_length=254,
widget=forms.TextInput(attrs={'class': "form-control input-lg",'placeholder': 'email'}),
)
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': "form-control input-lg",'placeholder': 'password'}))
password2 = forms.CharField(widget=forms.PasswordInput(attrs={'class': "form-control input-lg",'placeholder': 'confirm password'}),label="Confirm password")
class Meta:
model = User
fields = ('username', 'email', 'password','password2')
class UserProfileForm(forms.ModelForm):
website = forms.URLField(widget=forms.TextInput(attrs={'class': "form-control input-lg",'placeholder': 'website'}))
picture=form.Imagefield
class Meta:
model = UserProfile
fields = ('website', 'picture')
This is my views.py update and register
def register(request):
registered = False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
registered = True
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request,
'Survey/register.html',
{'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )
#login_required
def update(request):
updated = False
user = request.user
profile=request.userprofile
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
user_form = UserForm(data=request.POST,instance=user)
profile_form = UserProfileForm(data=request.POST,instance=profile)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
u = User.objects.get(username=user.username)
u.set_password(user.password)
u.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
update = True
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm(instance=user)
profile_form = UserProfileForm()
return render(request,
'Survey/update_profile.html.html',
{'user_form': user_form,'profile_form': profile_form,'updated': updated} )
I have two problems with this
I am able to retrieve the user information but not user profile information
The password field I updated is stored without hashing (during registration the password is stored with hashing) so I am unable to login with the new password as authentication fails
Any help?

Categories