models.py
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
# on_deleting user, profile will also be deleted
image = models.ImageField(default="profilepic.jpg",upload_to="profile_pictures")
dob = models.DateField(null=True)
bio = models.TextField(null=True)
anonymous = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.username} Profile'
views.py
#login_required
def profile_edit(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'your account has been updated')
return redirect('users:profile')
else:
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileForm()
context = {
'u_form' : u_form,
'p_form' : p_form
}
return render(request, 'users/profile_edit.html',context)
in users/profile_edit.html
<div class="form-group">
<label class="radio-inline"><input type="radio" name="anonymous" value='True'>Anonymous</label>
<label class="ml-5 radio-inline"><input type="radio" name="anonymous" value='False' checked>Non-Anonymous</label>
</div>
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name','last_name']
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image','dob','bio']
the rest of the form works fine (updates the contents of profile as expected) but the BooleanField for anonymous does not work when the radio buttons are clicked before submitting the form
after #harshil9968 asked for profile form, I realized that i had not included anonymous in my profileform, hence the output of radio button was not being processed on form submit
Related
Im registering succesfully user, but when ot redirects me to login page I'm 100% sure password is correct, but it is not login me in, so I checked the admin page for that particular user, username exists, but it says that the password is not created yet.
this is my views.py
#from selectors import EpollSelector
from django.shortcuts import render, redirect
from django.contrib import messages
from django.http import HttpResponseRedirect
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
from django.contrib.auth.decorators import login_required
# Create your views here
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
messages.success(request, f'You are now able to log in!')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'Users/register.html', {'form': form})
#login_required
def profile(request):
if request.method == "POST":
u_form = UserUpdateForm(request.POST, instance = request.user)
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'You account has been updated!')
return redirect('profile')
else:
u_form = UserUpdateForm(instance = request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'u_form' :u_form,
'p_form' :p_form
}
return render(request, 'Users/profile.html', context)
and this is my forms.py code
from socket import fromshare
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm
from .models import Profile
class UserRegisterForm(UserChangeForm):
email = forms.EmailField()
password1 = forms.CharField(label = "Password", widget = forms.PasswordInput)
password2 = forms.CharField(label = "Repeat password", widget = forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
Please suggest some solution. I was following Corey Schafer tutorial.
Try to read about django.contrib.auth and passwords.
https://docs.djangoproject.com/en/4.1/topics/auth/default/#changing-passwords
Django don't change password to hash, you should do it yourself before user.save()
in your case:
... # your staff
form = UserRegisterForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(form.cleaned_data['password'])
user.save()
username = user.username
messages.success(request, f'You are now able to log in!')
... # other staff
I need to display the details of the user on the profilepage. But in the following situation, I am unable to render phone number and flag(attributes of SpecialUser model) on my profile page. I was asked to implement an extended model for the User model in Django auth for an application. I introduced 2 new fields i.e, phonenumber(charfield), flag(booleanfield). My form is able to take both the inputs. But I couldn't render these values again into my HTML file. Could someone help me out!
models.py
# accounts.models.py
from django.db import models
from django.contrib.auth.models import User
class SpecialUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
flag = models.BooleanField(verbose_name="Special User", default=False)
phonenumber = models.CharField(max_length=10, verbose_name="phonenumber")
def __str__(self):
return self.user.username
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import SpecialUser
class RegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]
class SuperUserForm(forms.ModelForm):
class Meta:
model = SpecialUser
fields = ["flag", "phonenumber"]
views.py
from accounts.models import SpecialUser
from django.shortcuts import render, redirect
from .forms import RegisterForm, SuperUserForm
from django.contrib import messages
from django.contrib.auth.models import auth
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
sp_form = SuperUserForm(request.POST)
if form.is_valid() and sp_form.is_valid():
user = form.save()
sp_form = sp_form.save(commit=False)
sp_form.user = user
sp_form.save()
messages.success(request, 'Account created!')
return redirect('login')
else:
form = RegisterForm(request.POST)
sp_form = SuperUserForm(request.POST)
messages.warning(request, 'Your account cannot be created.')
return render(request, 'register.html', {'form': form, 'sp_form': sp_form})
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
data = SpecialUser.objects.all()
dt = {"all": data}
return render(request, "profilepage.html", dt)
else:
messages.info(request, 'invalid credentials')
return redirect('login')
else:
return render(request, 'login.html')
def logout(request):
auth.logout(request)
return redirect('login')
profilepage.html
<h1>{{user.username}}</h1>
<h4>Email : {{user.email}}</h4>
<h5>Phone Number : {{all.phonenumber}}</h5>
{%if user.flag %}
<button>Special User</button>
{%endif%}
here is the correct html you need to see your data
{%for d in all%}
{%ifequal d.user user%}
<h1>{{d.user.username}}</h1>
<h4>Email : {{d.user.email}}</h4>
<h5>Phone Number : {{d.phonenumber}}</h5>
{%if d.flag %}
<button>Special User</button>
{%endif%}
{%endifequal%}
{%endfor%}
I'm trying to create a new form in my form.py (AddressForm), but I get an error that says: local variable 'user_AddressForm' referenced before assignment
Could someone give me a hand please?
The username, password and image works fine, but the address form doesn't have persistent data and gives me the error
in my forms.py file:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class AddressForm(forms.Form):
address_1 = forms.CharField(
label='Address',
widget=forms.TextInput(attrs={'placeholder': '1234 Main St'})
)
address_2 = forms.CharField(
widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'})
)
city = forms.CharField()
state = forms.ChoiceField(choices=states)
zip_code = forms.CharField(label='Zip')
class Meta:
model = User
fields = ['address_1', 'address_2', 'city', 'state', 'zip_code']
in my views.py
from django.shortcuts import render, redirect
from django.contrib import messages # to display alert messages when the form data is valid
from .forms import UserSignUpForm, UserUpdateForm, ProfileUpdateForm, AddressForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth import update_session_auth_hash
#login_required
def profile(request):
if request.method == 'POST':
u_Passform = PasswordChangeForm(request.user, request.POST)
if u_Passform.is_valid():
u_Passform.save()
update_session_auth_hash(request, u_Passform)
messages.success(request, f'Your password was updated successfully. Please log back in')
return redirect('profile')
u_form = UserUpdateForm(request.POST, instance=request.user)
if u_form.is_valid:
u_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('profile')
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if p_form.is_valid():
p_form.save()
messages.success(request, f'Your Image was updated successfully!')
return redirect('profile')
user_AddressForm = AddressForm(request.POST, None)
if user_AddressForm.is_valid:
u_form.save()
messages.success(request, f'Your address has been updated!')
return redirect('profile')
else:
u_Passform = PasswordChangeForm(request.user)
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
context = {
'user_AddressForm': user_AddressForm,
'u_Passform': u_Passform,
'u_form': u_form,
'p_form': p_form
}
return render(request, 'users/profile.html', context)
In my profile.html:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<div class="card text-center">
<div class="card-header">
Profile Info
</div>
</div>
<p></p>
{{ u_form|crispy }} <!-- Public profile: Username, email, website url -->
{{ p_form|crispy }} <!-- Image form -->
{{ u_Passform|crispy }} <!-- Password reset form -->
{{ user_AddressForm|crispy }} <!-- Password reset form -->
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update</button>
</div>
</form>
This is the models.py:
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
# Profle model with data regarding the user
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address1 = models.CharField(
"Address line 1",
max_length=1024,
)
#Image feature upload
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
# If we don't have this, it's going to say profile object only
def __str__(self):
return f'{self.user.username} Profile' # it's going to print username Profile
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
Now... If I simply get the form from the forms.py file I'm able to display it on the screen, but it doesn't save the data.
Thanks for the help
You haven't defined user_AddressForm in the case the request method isn't 'POST'. Below p_form = ProfileUpdateForm... you should:
user_AddressForm = AddressForm(instance=request.user.user_profile)
that way it's also present for a GET request.
I am trying to create an "edit profile" page/form and have followed the SimpleIsBetterThanComplex tutorial on how to extend the user model by way of the OneToOne Link. However, when i try to display the user profile form to allow the user to update their profile, the form doesn't display at all except for the Submit button... Any ideas where i might have gone wrong here?
models.py
from __future__ import unicode_literals
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
from django.utils import timezone
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
#account types
is_userA = models.BooleanField('User A', default=True)
is_userB = models.BooleanField('User B', default=False)
is_superuser = models.BooleanField('SuperUser', default=False)
#other fields here
avatar = models.ImageField('avatar', upload_to='static/media/images/avatars/', null=True, blank=True)
phone = models.CharField('phone number', max_length=20, blank=True, default='')
address = models.CharField('address', max_length=100, default='', blank=True)
city = models.CharField('city', max_length=100, default='', blank=True)
state = models.CharField('state', max_length=2, default='', blank=True)
country = models.CharField('country', max_length=100, default='', blank=True)
date_joined = models.DateTimeField(default=timezone.now)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
views.py
#login_required
#transaction.atomic
def update_profile(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
if user_form.is_valid():
user_form.save()
messages.success(request, _('Your profile was successfully updated!'))
return redirect('settings:profile')
else:
messages.error(request, _('Please correct the error below.'))
else:
user_form = UserForm(instance=request.user)
return render(request, 'profiles/profile.html', {
'user_form': user_form,
})
template
<div class="col-md-12">
<div class="mb32">
<h5 class="uppercase">General Information</h5>
</div>
<div class="row">
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<button type="submit">Save changes</button>
</form>
Your view looks for now looks like this:
views.py
#login_required
#transaction.atomic
def update_profile(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
if user_form.is_valid():
user_form.save()
messages.success(request, _('Your profile was successfully updated!'))
return redirect('settings:profile')
else:
messages.error(request, _('Please correct the error below.'))
else:
user_form = UserForm(instance=request.user)
return render(request, 'profiles/profile.html', {
'user_form': user_form,
})
According to this view if method POST, you validate enterd data from the form, but when its GET method you just define UserForm, so i think you have to make indent in the last line:
views.py
#login_required
#transaction.atomic
def update_profile(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
if user_form.is_valid():
user_form.save()
messages.success(request, _('Your profile was successfully updated!'))
return redirect('settings:profile')
else:
messages.error(request, _('Please correct the error below.'))
else:
user_form = UserForm(instance=request.user)
return render(request, 'profiles/profile.html', {
'user_form': user_form,
})
So your last line return render(request, 'profiles/profile.html', {'user_form': user_form,}) have to be under else statement, cause its GET as I understand.
I want to fetch each and every detail of user profile. I know function get_profile() has been depreciated.
I want get user profile and then pass it as context to template.
Actually I am making a "Edit user profile" functionality.
My Model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
state = models.CharField(max_length=200, blank=True)
country = models.CharField(max_length=200, blank=True)
zipcode = models.CharField(max_length=200, blank=True)
And views:
#login_required
def dashboard(request):
context = RequestContext(request)
profile = request.user.userprofile
context_dict = {'profile': profile}
return render_to_response('appname/dashboard.html', context_dict, context)
To edit both User and Profile instance you have to use two forms:
class UserForm(forms.ModelForm):
class Meta:
class = User
fields = ('username', 'first_name', 'last_name')
class ProfileForm(forms.ModelForm):
class Meta:
class = UserProfile
exclude = ('user', )
#login_required
def edit_profile(request):
user = request.user
profile = user.userprofile
if request.method == 'POST':
user_form = UserForm(request.POST, instance=user)
profile_form = ProfileForm(request.POST, instance=profile)
if all([user_form.is_valid(), profile_form.is_valid()]):
user_form.save()
profile_form.save()
return redirect('.')
else:
user_form = UserForm(instance=user)
profile_form = ProfileForm(instance=profile)
return render(request, 'user_profile.html',
{'user_form': user_form, 'profile_form': profile_form})
And the template should contain both forms in the single <form> tag:
<form action="." method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<button>Update</button>
</form>