My question is when I give the wrong email or password, No error message is Shown, but why ?? and how can I fix that?
This is my signin View function
def signin(request):
form = AuthenticationForm(request=request, data=request.POST)
if form.is_valid() == True:
user = authenticate(email=form.cleaned_data['username'], password=form.cleaned_data['password'])
if user is not None:
login(request, user)
return HttpResponse(f'{request.user}')
else:
context = {'form': form}
return render(request, 'signin.html', context)
This is my Html
<form action="{% url 'signin' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
{{ field }} <br>
{% endfor %}
<button type="submit">Signin</button>
</form>
I think you need to add {{ form.non_field_errors }} to your template. This is because the error raised by unsuccessful authentication is not associated to a specific field, so it isn't included in any field's errors. Reference
Related
Im trying to render login and register view in a single template using variable assignment and if-else. I'm sorry if its a rookie mistake, Im pretty new to this..
github repo- https://github.com/varundhand/DevSearch
my urls.py :-
urlpatterns = [
path('login/',views.loginUser,name='login'),
path('logout/',views.logoutUser,name='logout'),
path('register/',views.registerUser,name='register'),
path('',views.profiles,name='profiles'),
path('profile/<str:pk>/',views.userProfile,name='user-profile'),
]
my views.py :-
def loginUser(request):
page = "login"
if request.user.is_authenticated:
return redirect('profiles')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
try:
user = User.objects.get(username=username)
except:
messages.error(request,'Username doesnt exist')
user = authenticate(request,username=username,password=password)
if user is not None:
login(request,user)
return redirect ('profiles')
else:
messages.error(request,'Username/Password incorrect')
context = {page:'page'}
return render(request, 'users/login_register.html', context)
def logoutUser(request):
logout(request)
messages.error(request,'User was logged out!')
return redirect('login')
def registerUser(request):
page = "register"
context= {page:'page'}
return render(request,'users/login_register.html', context)
my html template file :-
{% extends 'main.html' %}
{% block content %}
{% if page == "register" %}
<h1>Register User</h1>
<p>Already have an account? Login </p>
{% else %}
<form action="{% url 'login' %}" method="POST">
{% csrf_token %}
<input type="text" name="username" placeholder="Username">
<input type="pass`your text`word" name="password" placeholder="Enter Password">
<input type="submit" value="Login">
<p>Dont have an account? Sign Up</p>
</form>
{% endif %}
{% endblock content %}
My Approach
I gave variable assignment of page='login' and page='register' in loginUser and registerUser view respectively and then i gave an if-else in my common template but for some reason only loginUser view is working even when i go to the register url.
Ignore my silly question, I was passing the wrong context dictionary i.e. it shoulda been context = {'page':page}
I'm creating an app in which I'd like to use my own custom login form with a captcha field. My intention is to do this without using an external library (except for requests) but I couldn't add captcha field to my custom form in forms.py, so I added it directly to login.html but for some reason when I do form.is_valid() it returns an error.
I've already seen the solutions in Django - adding google recaptcha v2 to login form and Adding a Recaptcha form to my Django login page but as I said, I'd like to do this without using an external library.
views.py
...
def login_view(request):
if request.method == 'POST':
form = CustomLoginForm(request.POST)
result = is_recaptcha_valid(request)
print(result) # prints True
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
# Redirect to index
messages.success(request, "Logged in.")
return HttpResponseRedirect(reverse('orders:index'))
else:
messages.error(request, "Invalid credentials.")
else:
print("error")
return render(request, 'registration/login.html', {'form': CustomLoginForm()})
else:
form = CustomLoginForm()
return render(request, 'registration/login.html', {'form': form})
forms.py
class CustomLoginForm(AuthenticationForm):
email = forms.EmailField(
error_messages={
'required': 'Please enter your email.',
'invalid': 'Enter a valid email address.'
},
help_text='Email',
)
login.html
<form class="" action="{% url 'orders:login' %}" method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<!-- ReCAPTCHAV3 -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey='key-here'></div>
<button class="btn btn-success" type="submit" name="">Login</button>
<!-- <input type="hidden" name="next" value="{{ next }}"> -->
</form>
is_recaptcha_valid() function already returns True so I didn't share that. I'm a beginner in Django, so if you can please explain in two words what I've done wrong instead of just posting the answer, I'd be grateful. Thank you for your time.
The AuthenticationForm is slightly different than the others..
If your check AuthenticationForm class, AuthenticationForm 's first arguments is not data like others form:
class AuthenticationForm(forms.Form):
...
def __init__(self, request=None, *args, **kwargs):
...
Thats why you need to pass request.POST to data.
So update your code like this:
def login_view(request):
if request.method == 'POST':
form = CustomLoginForm(data=request.POST)
...
guys i need a small help
here is my views.py
def signup(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
verification=VerificationForm(request.POST)
if form.is_valid():
userObj = form.cleaned_data
username = userObj['username']
email = userObj['email']
password = userObj['password']
return HttpResponseRedirect('/index/verification/')
# if
if not (User.objects.filter(username=username).exists() or User.objects.filter(email=email).exists()):
User.objects.create_user(username, email, password)
user = authenticate(username = username, password = password)
login(request, user)
return HttpResponseRedirect('/')
else:
raise forms.ValidationError('Looks like a username with that email or password already exists')
else:
raise forms.ValidationError('a valid')
else:
form = UserRegistrationForm()
verification = VerificationForm()
return render(request, 'question/signup.html',context= {'verification':verification,'form' : form})
here you can see i have declared two context variables one is form and the other one is verification now i want to use
now this is my signup.html
{% extends 'question/index.html '%}
{% block body_block %}
<div class="conrainer">
<form method="POST">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Submit</button>
</form>
facebook auth
</div>
{% endblock %}
now i have used form variable in this page
and i want to use verification varible in another page as django views are not made to use two templates in a single view
after searching a lot in online forums i came to know about {% include tag %}
after trying to use that tag after going through documentation
this is how my verification.html is
{% include 'question/signup.html' with obj=verification only%}
<div class="container">
<form method="post">{% csrf_token %}
<p>{{verification.as_p}}</p>
<p>{{obj.as_p}}</p>
<input type="submit" name="verify" value="" action='.' align='center'name='submit'>
</form>
</div>
here is my urls.py file
urlpatterns = [
# url(r'^/',views.home,name='home'),
url(r'^home/',Home,name='home'),
url(r'^ques/',Create.as_view(success_url="/index/home/"),name='ques'),
url(r'^signup/',signup,name='signup'),
# url(r'^signup/',MyFormView.as_view(),name='signup'),
url(r'^verification/',TemplateView.as_view(template_name="question/verification.html")),
url(r'^logout/$', auth_views.logout,name='logout'),
url(r'^search/',Search,name='search'),
url(r'^accounts/', include('allauth.urls')),
# url(r'^verify/',verificationView,name='signup'),
# CreateView.as_view(model=myModel, success_url=reverse('success-url'))
]
but after trying it so many ways either obj or verification shows up in the site is there any way where i can only get the context object instead of getting the subit button and all from my signup.html using INCLUDE any kind of help is appreciated
I have the following form that works in its own view, that I am trying to set up as a template tag.
#login_required
#register.inclusion_tag('posts/new_post_form.html', takes_context = True)
def newpostform(context):
request = context['request']
if request.user.is_authenticated():
post_form_local = PostFormLocal(request.POST or None)
user = request.user
if post_form_local.is_valid():
save_form = post_form_local.save(commit=False)
save_form.user = request.user
save_form.save()
messages.success(request, 'Post Saved')
return HttpResponseRedirect('/post/%d/' % save_form.id)
else:
return {'post_form_local': PostFormLocal(), 'user': user}
The form appears on a page fine by calling:
{% load newpost %}
{% newpostform %}
(and I am using Crispy Forms with this)
new_post_form.html looks like:
{% load url from future %}
{% load crispy_forms_tags %}
<form method="POST" action=""> {% csrf_token %}
<h3>Create New Post</h3>
{% crispy post_form_local %}
</form>
The form appears ok, submits, but then comes up with an error:
VariableDoesNotExist at...(current page)
Failed lookup for key [post_form_local] in u"[{'False': False, 'None': None, 'True': True}, ]"
If I refresh this page, the post is saved and appears as normal - can't figure out what I am missing here, any thoughts?
I've built a "firewall" login form that I want to put in front of my
actual production website while I develop the site. The idea is to try
and keep the "bad guys" out of the site and at the same time see what
usernames and passwords they're using. The problem I'm having is that
if I enter an invalid username/password pair, my form's error message
doesn't get displayed. I realize that for my purposes, it it might be
better to not display any error message at all but I'd still like to
understand what the problem is. Can anyone see what I'm doing wrong?
Thanks.
# views.py
import logging
logger = logging.getLogger(__name__)
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.views import login
from django.http import HttpResponseRedirect
def firewall_login(request, *args, **kwargs):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
username = request.POST['username']
password = request.POST['password']
if form.is_valid():
fw_username = form.cleaned_data['username']
fw_password = form.cleaned_data['password']
user = authenticate(username=fw_username, password=fw_password)
if user is not None:
if user.is_active:
login(request, user)
logger.info("User '%s' logged in." % fw_username)
return HttpResponseRedirect("/accounts/profile/")
else:
logger.info("User '%s' tried to log in to disabled account." % fw_username)
return HttpResponseRedirect("/accounts/disabled/")
else:
logger.info("User '%s' tried to log in with password '%s'." % (username, password))
form = AuthenticationForm(request) # Display bound form
else:
form = AuthenticationForm() # Display unbound form
return render(request, "registration/login.html", {"form": form,})
# login.html
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p class="alert alert-error">Sorry, that's not a valid username or password</p>
{% endif %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for field in form.non_field_errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form action="" method="post">
{% csrf_token %}
<p><label for="username">Username:</label>{{ form.username }}</p>
<p><label for="password">Password:</label>{{ form.password }}</p>
<input type="hidden" name="next" value="{{ next|escape }}" />
<input class="btn btn-primary" type="submit" value="login" />
</form>
{% endblock %}
It's because you pass new form instance. Validation occurs on is_valid call.
So, just remove form = AuthenticationForm(request) in else block:
def firewall_login(request, *args, **kwargs):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
username = request.POST['username']
password = request.POST['password']
if form.is_valid():
fw_username = form.cleaned_data['username']
fw_password = form.cleaned_data['password']
user = authenticate(username=fw_username, password=fw_password)
if user is not None:
if user.is_active:
login(request, user)
logger.info("User '%s' logged in." % fw_username)
return HttpResponseRedirect("/accounts/profile/")
else:
logger.info("User '%s' tried to log in to disabled account." % fw_username)
return HttpResponseRedirect("/accounts/disabled/")
else:
logger.info("User '%s' tried to log in with password '%s'." % (username, password))
else:
form = AuthenticationForm() # Display unbound form
return render(request, "registration/login.html", {"form": form,})