def profile(request):
Exist_Emails = User.objects.filter(is_active=True).values_list('email', flat=True)
Exist_Usernames = User.objects.filter(is_active=True).values_list('username', flat=True)
current_user = User.objects.get(username=request.user.username)
Email_Invalid = False
Username_Invalid = False
if request.method != 'POST':
u_form = UserUpdateForm(instance=request.user)
p_form = ProfileUpdateForm(instance=request.user.profile)
else:
update_username = request.POST.get('username')
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():
p_form.save()
update_u_form = u_form.save(commit=False)
#Problem occurs in this if statement!
if update_u_form.username in Exist_Usernames and update_u_form.username != current_user.username:
Username_Invalid = True
u_form = UserUpdateForm(instance=current_user) ##
messages.error(request, 'The username already eixts')
#But it worked in this elif statement which is almost the same!
elif update_u_form.email in Exist_Emails and update_u_form.email != current_user.email:
Email_Invalid = True
u_form = UserUpdateForm(instance=current_user)
messages.error(request, 'The email already exits.')
else:
update_u_form.save()
return redirect('/users/profile/')
context = {
'u_form': u_form, 'p_form': p_form,'update_username':
update_username,'Email_Invalid': Email_Invalid,'current_user':
current_user, 'Username_Invalid': Username_Invalid}
return render(request, 'users/profile.html', context)
This is the html template:
{% if Email_Invalid == "True" or Username_Invalid == "True" %}
{{ current_user.username }}
</div>
<div style="font-size:16px;">
{{ current_user.email }}
</div>
<p>"Sorry, the email or username already exits."</p>
{% else %}
{{ user.username }}
</div>
<div style="font-size:16px;">
{{ user.email }}
</div>
{% endif %}
{{Username_Invalid}}
{{update_username}}
<form method="post" class="form" enctype="multipart/form-data">
{% csrf_token %}
{{ u_form.as_p }}
{{ p_form.as_p }}
<button name="sumbit" class="btn btn-primary" >Update</button>
</form>
My forms.py:
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email']
As I type in updated username, and press submit. However The {{Username_Invalid}} returns False which is supposed to be True in if statement.
Then I checked {{update_username}} which returns NONE!! update_username here is just request.POST.get('username').
What is going on? I thought UserUpdateForm should inherit from User model. So request.POST should have a dictionary key-value pair 'username':username.
My debugging process:
What I am trying to do is to display (instance = current_user) in u_form when the user tries to edit email or username but these email or username has already been registered in database by others.
It works perfectly fine in the email field, but when I edit username to be sth that has already been registered by another user, the instance however displays whatever I typed in(It should print instance = current_user not request.user).
So I found out that when I did this , it didn't enter the first IF statement after is_valid, as Username_Invalid still prints False. Then I checked if something is wrong with 'update_u_form.username' , so I set
update_username = request.POST.get('username')
to print out the value, and it returns NONE. I think this is where the problem is but can't figure out why.
Related
I have created a page to update User profile. If I try to update a value of user with existing user, error is thrown as expected, however the variable user.username in profile.html shows the value I am trying to update. My query is why {{ user.username }} is picking up the incorrect value even though the save() method is not called.
profile.html
<div class="content p-3">
<div><img class="rounded-circle" src="{{ user.profile.image.url }}" width="100" height="100"></div>
<div>{{ user.username }}</div>
<div>{{ user.email }}</div>
</div>
<div class="w-25">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend>Profile Info</legend>
{{ user_form | crispy }}
{{ profile_form | crispy }}
</fieldset>
<input class="mt-3" type="submit" value="Update">
</form>
</div>
forms.py
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
views.py
#login_required
def profile(request):
if (request.method == "POST"):
user_form = UserUpdateForm(request.POST, instance=request.user)
profile_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if (user_form.is_valid() and profile_form.is_valid()):
user_form.save()
profile_form.save()
messages.success(request, f"Your profile is updated successfully")
return redirect("profile")
else:
messages.error(request, f"Failed to update profile")
else:
user_form = UserUpdateForm(instance=request.user)
profile_form = ProfileUpdateForm(instance=request.user.profile)
return render(request, 'User/profile.html', {'user_form': user_form, 'profile_form': profile_form}
The ModelForm updating the instance as part of validation is strange/unwanted behaviour, maybe you have found a "bug"
A work around would be to pass a copy of request.user using copy.copy into the ModelForm so that any changes made as part of validation happen on the copy
user_form = UserUpdateForm(request.POST, instance=copy.copy(request.user))
When you write user_form = UserUpdateForm(request.POST, instance=request.user),
your user_form update itself using the values received from front-end. In this case, username is 'newuser2'.
Since this username is taken, user_form.is_valid() returns false and below render function is returned:
return render(request, 'User/profile.html', {'user_form': user_form, 'profile_form': profile_form}
Please note that this instance of user_form has username as "newuser2". Thats why you see username as "newuser2" instead of your current logged in user.
Apologies for the brevity, I'm learning to post answers.
I Want To Create A User Like Signup or register when i hit submit button i got this error:
UnboundLocalError at /signup/
i want to signup user:
local variable 'usercustom' referenced before assignment
here is my Views.py
def signup(request):
registered = False
if request.method == "POST":
user_form = UserForm(request.POST or None)
custom_form = UserCustom(request.POST or None)
if user_form.is_valid() and custom_form.is_valid():
user = user_form.save(commit=False)
user.save()
custom = custom_form.save(commit=False)
custom.user = user
custom.save()
registered = True
else:
print(user_form.errors,custom_form.errors)
else:
user_form = UserForm()
usercustom = UserCustom()
return render(request,'form.html',{'user_form':user_form,'usercustom':usercustom,'registered':registered})
here is my Form.html
{% extends "base.html" %}
{% block body_block %}
<div class="content-section">
{% if registerd %}
<h1>Thank Your For registering!</h1>
{% else %}
<h1>Register Here</h1>
<h3>Fill out the form</h3>
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ usercustom.as_p }}
<input type="submit" value="Register!" class="btn btn-danger">
</form>
{% endif %}
</div>
{% endblock %}
It is because usercustom is not declared when you tried to send POST request. You need to rename custom_form variable to usercustom. I have simplified your code for you.
def signup(request):
registered = False
if request.method == "POST":
user_form = UserForm(request.POST or None)
usercustom = UserCustom(request.POST or None)
if user_form.is_valid() and usercustom.is_valid():
user = user_form.save(commit=False)
user.save()
custom = usercustom.save(commit=False)
custom.user = user
custom.save()
registered = True
else:
print(user_form.errors, usercustom.errors)
else:
user_form = UserForm()
usercustom = UserCustom()
return render(request,'form.html',{'user_form':user_form,'usercustom':usercustom,'registered':registered})
To new readers: Neverwalkaloner's solution solved the initial error but the photo upload is still required and making required false in forms.py gives me a MultiValueDictKeyError. Any help on making it optional would be greatly appreciated.
I have a model and form to upload either a picture and text, or just text. My intention, actually was to make it a choice between an image, text or both and any help with that would be appreciated, but I digress. Uploading only works when an image is included, if it is just text, I get the error:
The view lesyeux.views.posts didn't return an HttpResponse object. It
returned None instead.The view lesyeux
My model is:
class Post(models.Model):
image = models.ImageField(upload_to='uploaded_images', blank=True,
null=True)
text_post = models.CharField(max_length=1000)
author = models.ForeignKey(User)
My form is:
class PostForm(forms.ModelForm):
image = forms.FileField(label='Select an image file',
help_text='Please select a photo to upload')
text_post = forms.CharField(help_text="Please enter some text.")
class Meta:
model = Post
fields = ('image', 'text_post',)
exclude = ('author',)
My view is:
def posts(request, id=None):
neighborhood = get_object_or_404(Neighborhood, id=id)
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = Post(image = request.FILES['image'])
post = form.save(commit=False)
post.author = request.user
post = post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
else:
form = PostForm()
posts = Post.objects.all().order_by('-id')
return render(request, 'posts.html', context = {'form':form,
'posts':posts, 'neighborhood':neighborhood})
and my form is:
<form id="PostForm" method="post" action="/view/{{ neighborhood.id }}/posts/" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="submit" name="submit" value="Post" />
</form>
Your view doesnt return response if form is not valid. To fixt it rewrite view like this:
def posts(request, id=None):
neighborhood = get_object_or_404(Neighborhood, id=id)
form = PostForm()
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = Post(image = request.FILES['image'])
post = form.save(commit=False)
post.author = request.user
post = post.save()
next = request.POST.get('next', '/')
return HttpResponseRedirect(next)
else:
form = PostForm()
posts = Post.objects.all().order_by('-id')
return render(request, 'posts.html', context = {'form':form, 'posts':posts, 'neighborhood':neighborhood})
I don't want to display the verifications on the screen neither on username nor on password until a user fills invalid data, how can I do that ?!
Here is my user form in forms.py :
class UserForm(UserCreationForm):
class Meta():
model = User
fields = ('username','first_name','last_name','email','password1','password2',)
def save(self,commit=True):
user = super(UserForm,self).save(commit=False)
user.username = self.cleaned_data["username"]
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.password1 = self.cleaned_data["password1"]
user.password2 = self.cleaned_data["password2"]
if commit:
user.save()
return user
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = 'Username'
self.fields['first_name'].label = 'First Name'
self.fields['last_name'].label = 'Last Name'
self.fields['email'].label = 'Email Address'
self.fields['password1'].label = 'Password'
self.fields['password2'].label = 'Re-enter Password'
and here is my registration function :
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.password1)
user.save()
c_user = user_form.instance.id
profile = profile_form.save(commit=False)
profile_form.instance.userid = AuthUser(c_user)
profile.save()
if 'profilepic' in request.FILES:
profile.profilepic = request.FILES['profilepic']
profile.save()
registered = True
else:
print(user_form.errors)
print(profile_form.errors)
else:
user_form = UserForm
profile_form = UserProfileForm
return render(request,'registration/register.html',{'user_form':user_form,'profile_form':profile_form,'registered':registered})
My registration page
My registration template
use this template:
<div class="container">
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<form method="post">
{% csrf_token %}
<div class="panel panel-default text-center">
<h2>Sign up!</h2>
</div>
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">Signup!</button>
</form>
</div>
</div>
this will show errors when the user type invalid data.
Heyho,
I created a model Profile with a OnetoOneField to User. In account_settings view I want to either give the possibility to change the profile information or reset the password. Changing Profile-Information works fine, but when I try to change the password, my PasswordChangeForm is always invalid. Can somebody tell me where my mistake is?
Here's the view:
def account_settings(request, id):
user = Profile.objects.get(id=id)
if request.method == 'POST' and 'passwordchange' in request.POST:
user_form = PasswordChangeForm(request.user, prefix='password')
if user_form.is_valid():
user_form.save()
update_session_auth_hash(request, user)
messages.success(request, 'Your password was successfully updated!')
else:
messages.error(request, 'Please correct the error below.')
return redirect('profile', user.id)
elif request.method == 'POST' and 'profilechange' in request.POST:
profile_form = ProfileForm(request.POST, instance=request.user.profile,prefix='profil')
if profile_form.is_valid():
profile_form.save()
return redirect('account_settings',user.id)
#else:
#messages.error(request, _('Please correct the error below.'))
else:
user_form = PasswordChangeForm(user=request.user, prefix='password')
profile_form = ProfileForm(instance=request.user.profile,prefix='profil')
return render(request, 'app/accountform.html', {'profileuser': user,'user_form': user_form,'profile_form': profile_form})
the template:
<div class="col-md-9">
<div class="profile-content">
<form method="post" >
{% csrf_token %}
{{ profile_form.as_p }}
<button type="submit" name="profilechange">Ă„nderungen speichern</button>
</form>
<form method="post" >
{% csrf_token %}
{{ user_form.as_p }}
<button type="submit" name="passwordchange">Passwort ändern</button>
</form>
Abbrechen
</div>
</div>
You are not passing the POST data to the form, which is why it is failing to validate. You need to pass the POST data when initialising it:
user_form = PasswordChangeForm(request.user, data=request.POST, prefix='password')
if user_form.is_valid():
# This should work now