Why does a form not need an 'action' attribute? UserCreationForm - python

I create a form using django auth forms UserCreationForm and it works without 'action' inside . Why it works?
views.py
def sign_up(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect('contacts:index')
else:
form = UserCreationForm()
return render(request, 'account/signup.html', {'form': form})
sgnup.html
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up!</button>
</form>

Because by default your browser will post the form to the current URL. So if your get view and post view share the same URL, it just works.
And that's obviously the case here, since you use the same view for POST and GET.

As said by #dirkgroten, in HTML5 it is not mandatory to specify form action, in such cases like yours, with no action specified-The form is posted to current URL.

Related

Django Multiple Form on same page interact with each other

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!

The login function in Django not working properly

views.py
def login_view(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username,
password=password)
if user is not None:
login(request,user)
messages.info(request,'登入成功!')
return redirect('index')
else:
messages.error(request,'帳戶無效或密碼錯誤! 請重試!')
else:
messages.error(request,'帳戶無效或密碼錯誤! 請重試!')
context = {'form':form}
return render(request,'customer/login.html',context)
login.html
<form method="POST" action="" style="position:absolute;top:300px;left:125px;">
{% csrf_token %}
{{ form.username|as_crispy_field }}<br>
{{ form.password|as_crispy_field }}<br>
<button class="btn btn-primary" type="submit">登入</button>
</form>
For the login function in Django, I am trying to use the username and password based on the User model in django.contrib.auth.models to login into the account. However, even though I am using my superuser status to login and the error message appears showing that invalid username or password. May I ask is AuthenticationForm following the User model information to authenticate the user or anything I am missing?
You need to provide the 'data' attribute to the AuthenticationForm. Try this:
def login_view(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
login(request, form.get_user())
messages.info(request,'登入成功!')
return redirect('index')
else:
messages.error(request,'帳戶無效或密碼錯誤! 請重試!')
context = {'form':form}
return render(request,'customer/login.html',context)
The AuthenticationForm already does the authentication for you, so there is no need to run the authenticate function in your code again. You can get the user object for logging in using form.get_user() if the form is valid.

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})

Display User Profile getting ERROR: 'AnonymousUser' object has no attribute '_meta'

I have a simple view that is suppose to check if there is post data,
if so update the user data using UserChangeForm. Else get the form
data of user and display.
Issue: AttributeError at /profile/edit 'AnonymousUser' object has no
attribute '_meta'
I think it might be this line in the edit_profile view
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
Not sure what. Here is the view.py edit_profile
def edit_profile(request):
# Handle post request - if the user submits a form change form details and pass the intance user
if request.method == 'POST':
form = UserChangeForm(request.POST, intance=request.user)
if form.is_valid():
form.save()
return redirect('accounts/profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
profile_edit.html
{% extends 'base.html' %}
{% block head %}
<title>Profile</title>
{% endblock %}
{% block body %}
<div class="container">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save Changes</button>
</form>
</div>
{% endblock %}
You can't update an AnnonymousUser (that is special user class set for not logged in users). One solution of your problem is to disallow viewing this page by not authenticated user by decorating your view using login_required decorator.
You got error because there is not user logged in.
You can instead use try method.
In your code use if user.is_authenticated
if user.is_authenticated():
if request.method == 'POST':
form = UserChangeForm(request.POST, intance=request.user)
if form.is_valid():
form.save()
return redirect('accounts/profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = UserChangeForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
else:
raise PermissionDenied

MultiValueDictKeyError: "'password'"

My url is shown below like:
url(r'^register/$', views.register, name='register')
The function in my views.py is like:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.forms import UserCreationForm
def register(request):
"""register"""
if request.method != 'POST':
#we present a blank form
form = UserCreationForm()
else:
#the post the data the users have just filled
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
# we use the date to redirect our user to the page of login
authenticated_user = authenticate(username=new_user.username,
password=request.POST['password'])
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)
And my register.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<form action="{% url 'users:register' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button name="submmit">Register</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}"/>
</form>
{% endblock content %}
when I do the register, it goes wrong like, MultiValueDictKeyError: "'password'"
Can some one have a look and give me a hand? Thanks a lot!
If you check UserCreationForm, you'll see that it doesn't have a field named password, but it has two: password1 and password2. You can change your code to this:
if form.is_valid():
new_user = form.save()
# we use the date to redirect our user to the page of login
authenticated_user = authenticate(username=new_user.username,
password=form.cleaned_data['password1'])
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
However, you probably want to avoid dealing with passwords and simply use login() directly, without passing through authenticate():
if form.is_valid():
user = form.save()
login(request, user)
return HttpResponseRedirect(reverse('learning_logs:index'))

Categories

Resources