Django Multiple Form on same page interact with each other - python

I have a page with two forms. When I click on the button Update Profile on the left Form it also send the POST request to the the second form which is not what I want. I don't want them to interact together. How can I do that?
views.py
#login_required(login_url='signin')
def dashboard(request):
global user_id
data = Account.objects.filter(user=request.user)
profile_data = Profile.objects.get(user=request.user)
profile_form = ProfileForm(request.POST or None, instance=profile_data)
addaccount_form = AddAccountForm(request.POST or None)
# Update Profile Settings
if profile_form.is_valid():
print("worked")
profile_form.save()
if request.method == "POST":
if addaccount_form.is_valid():
# save account to DataBase
return HttpResponseRedirect("http://127.0.0.1:7000/dashboard/")
context = {
'data': data,
'profile_form': profile_form,
'addaccount_form': addaccount_form,
}
return render(request, "main/dashboard.html", context)
dashboard.html
<form action="" method="POST">
{% csrf_token %}
{{profile_form}}
<button type="submit" class="updatebut">Update Profile</button>
</form>
<form action="" method="POST">
{% csrf_token %}
{{addaccount_form}}
<button type="submit" class="addbut">Add Account</button>
</form>

You can check which form in your request
if 'profile_form' in request.POST:
profile_form = ProfileForm(request.POST or None, instance=profile_data)
if profile_form.is_valid():
print("worked")
profile_form.save()
elif 'addaccount_form' in request.POST:
addaccount_form = AddAccountForm(request.POST or None)
if addaccount_form.is_valid():
# save account to DataBase
return HttpResponseRedirect("http://127.0.0.1:7000/dashboard/")

You can add a name to each one of your submit buttons (ex. name="addaccount" and name="updateprofile")
And in your view, add the following:
if 'addaccount' in request.POST:
---do the addacount
elif 'updateprofile' in request.POST:
---do the profile update
Quick and dirty!

Related

Why my form not sowing any validation errors after i click the submit button in django?

I've two forms rendering in a single function based view, it is diplaying validation errors of only one form when i click the signup button but when i click the login button it just reload my page
and doesn't showing any validation error
views.py
def register(request):
form = RegisterForm()
form_b = LogInForm()
if request.POST.get('submit') == 'sign_up':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
elif request.POST.get('submit') == 'log_in':
form1 = LogInForm(request=request, data=request.POST)
if form1.is_valid():
uname = form1.cleaned_data['username']
upass = form1.cleaned_data['password']
user = authenticate(username=uname, password=upass)
if user is not None:
login(request, user)
return redirect('/shop/')
else:
form = RegisterForm()
form_b = LogInForm()
return render(request, 'reg.html', {'form': form, 'form1': form_b})
forms.py
from distutils.command.clean import clean
from xml.dom import ValidationErr
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
password1 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username', 'email']
class LogInForm(AuthenticationForm):
username = forms.CharField(widget=forms.TextInput())
password = forms.CharField(widget=forms.PasswordInput())
reg.html
<form class="loginForm" action="" method="POST" novalidate>
{% csrf_token %}
{% for field in form %}
<p> {{field.label_tag}} {{field}} </p>
<p> {{field.errors}} </p>
{% endfor %}
<button type="submit" class="btnLogin" name='submit' value='sign_up'>Sign Up</button>
</form>
<form class="loginForm" action="" method="post" novalidate>
{% csrf_token %}
{% for field in form1 %}
<p> {{field.label_tag}} {{field}} </p>
<p> {{field.errors | striptags}} </p>
{% endfor %}
<button class="btnLogin" type="submit" name='submit' value='log_in'>Log In </button>
</form>
Try to create seperate view for both register and login.
try this way:
views.py:
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid:
form.save()
username = form.cleaned_data.get('username')
# messages.success(request,f'Welcome { username }')
return HttpResponseRedirect('/users/')
else:
form = RegisterForm()
return render(request,'users/register.html',{'form':form})
And in urls.py:
path('login',auth_views.LoginView.as_view(template_name='users/login.html'),name='login'),

how can I use LoginView in my own view and show in HTML templates?

I want to use ready Django LoginView, but in the same time I have to use my own view for registration in same HTML template. If in urls.py file I will connect 2 views than i will connect only first. So my question is that how can use LoginView in my own view and use 2 forms with jinja?
here is my views.py file and html ;)
def index(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
if 'signup' in request.POST:
if form.is_valid():
form.supervalid()
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Dear {username} you have been created a new accound!')
return redirect('main')
elif 'login' in request.POST:
if formlog.is_valid():
formlog.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('main')
else:
form = UserRegisterForm()
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
# this code is not working , but not returning any errors
HTML
{% if not user.is_authenticated %}
<!-- Login -->
<div class="container">
<div class="log-1">
<div class="log-0">
<p class="logtitle">BareTalk</p>
<form method="POST" name="login">
{% csrf_token %}
{{ formlog|crispy }}
<button class="log-button first" type="submit">Login</button>
</form>
<button class="log-button second"
onclick="modalwindowops.open();" id="signup">Sign Up</button>
</div>
</div>
</div>
<!-- Signup -->
<div class="modal-overlay">
<div class="modal-window">
<span class="close-modal" onclick="modalwindowops.close();">×</span>
<form method="POST" name="signup">
<p>Sign Up</p>
{% csrf_token %}
{{ form|crispy }}
<button type="submit">Sign Up</button>
</form>
</div>
</div>
{% else %}
<h1>Welcome back Amigo!</h1>
{% endif %}
Neither if 'signup' in request.POST: nor elif 'login' in request.POST: is triggered in your index() view because your HTML forms do not actually contain those inputs. Note that the name attribute is deprecated for the <form> element.
Instead you can add a hidden <input> inside your forms, like this:
<form method="POST">
{% csrf_token %}
{{ formlog|crispy }}
<input type="hidden" name="login" value="true" />
<button class="log-button first" type="submit">Login</button>
</form>
Also,
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
saves a view to formlog, not a form, so calling formlog.is_valid() will cause an error.
Instead of
elif 'login' in request.POST:
if formlog.is_valid():
formlog.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('main')
you probably will only need to do
elif 'login' in request.POST:
log_view = auth_views.LoginView.as_view(template_name='main/index.html')
log_view(request)
Calling is_valid(), save(), and doing the redirect is all done by LoginView already. If you want to still do the custom message.success() you will have to override one or more of the LoginView methods, but that is another topic.
Update:
You also need to change this line in the view: formlog = auth_views.LoginView.as_view(template_name='main/index.html') (before return render...) to:
formlog = AuthenticationForm(request)
Take this line outside of the else block.
Also add the import for the form at the top of your views.py:
from django.contrib.auth.forms import AuthenticationForm
This change is required because the template needs the form object (which is AuthenticationForm for LoginView by default) instead of the view object. The updated view function will look like:
from django.contrib.auth.forms import AuthenticationForm
def index(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if 'signup' in request.POST:
if form.is_valid():
form.supervalid()
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Dear {username} you have been created a new accound!')
return redirect('main')
elif 'login' in request.POST:
log_view = auth_views.LoginView.as_view(template_name='main/index.html')
log_view(request)
else:
form = UserRegisterForm()
formlog = AuthenticationForm(request)
return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
Note that this can be improved by providing feedback when the login credentials are invalid. As it is, this updated code only reloads a blank login form if the provided credentials don't work.

How to keep fields values after submit in Django?

I have a form and I would like to keep the values of the fields after a click on submit. How can I do this?
Views.py :
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
form.save()
else:
form = MyForm()
template.html
<form method="post" id="Myform" >
{{form}}
<button class="btn btn-primary" type="submit" >
</form>
Moving initial form assignment outside the check for the POST method should do.
form = MyForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.save()

Django form requires resubmission

I have a simple form in Django, and in my template I want to display each individual object for the whole queryset which I am saving the form to. The error I am getting is that my form does not seem to submit on the first attempt. Only when I click the submit button, manually refresh the page and then 'confirm form resubmission' do I see my updated queryset objects displayed in the template.
I am saving my form like this in my views:
exercise_name = ExerciseName.objects.all()
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
else:
form = ExerciseNameForm()
and passing the queryset to the template through the following context:
{ 'exercise_name': exercise_name }
and iterating through it like
{% for exercise_title in exercise_name %}
#content displaying each iteration
{% endfor %}
with my form to update it like:
<div>
<form method = "POST">{% csrf_token %}
{{form.as_p}}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
I am not sure why it is making me refresh the page and resubmit the form again in order to see the updated queryset after submitting the form?
You should be doing something like this:
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
return HttpResponse("data submitted successfully")
else:
return render(request, "your_template.html", {'form':form})
else:
form = ExerciseNameForm()
return render(request, "your_template.html", {'form':form})

Django User Profile doesn't update

I am setting up a website in Django, where users can see their profiles and update details (like email, password, etc) or delete own account. But updating the form is not acknowledged at all by the user. I am using the standard built-in User model.
forms.py:
class UserDetailsForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta:
model = User
fields = ('first_name','last_name','email','password','is_active')
views.py:
#login_required
def edit_profile(request):
user = User.objects.get(username=request.user)
form = UserDetailsForm(request.POST or None,
initial={'first_name':user.first_name,
'last_name':user.last_name,
'email':user.email,
'password':user.password,
'is_active':user.is_active,})
if request.method == 'POST':
if form.is_valid():
user.save()
messages.info(request, 'This is a debug message')
return HttpResponseRedirect(reverse('account'))
context = {"form": form}
return render(request, "iFood/user-account.html", context)
user-profile.html:
...
<form method="POST" action="{% url 'account' %}" class="" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="" value="Edit and Save">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="{{ message.tags }}">
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
First of all you can't change a password like that. You should take the password that user entered and set it with user_obj.set_password():
Django docs: Change password
And for your form:
You doing it wrong with user.save(). There is nothing to save for user object. You should save the form using form.save().
Also request.user is the actual user object not the username.
forms.py:
class UserDetailsForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta:
model = User
fields = ('first_name','last_name','email'','is_active')
views.py:
#login_required
def edit_profile(request):
user = request.user
form = UserDetailsForm(request.POST or None, instance=user)
if request.method == 'POST':
if form.is_valid():
# Save the changes but password
form.save()
# Change password
new_password = form.cleaned_data.get('password')
if new_password:
user.set_password(new_pass)
messages.info(request, 'This is a debug message')
return HttpResponseRedirect(reverse('account'))
context = {"form": form}
return render(request, "iFood/user-account.html", context)

Categories

Resources