How to implement forget password functionality using Django and Python - python

I need one help. I need to implement the forget password functionality using Django. I am using the Django signup and login page. My code is below:
login.html:
{% extends 'base.html' %}
{% block content %}
<h2>Log in</h2>
{% if form.errors %}
<p style="color: red">Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}<br>
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
{% if field.help_text %}
<p><small style="color: grey">{{ field.help_text }}</small></p>
{% endif %}
</p>
{% endfor %}
<button type="submit">Log in</button>
New to My Site? Sign up
</form>
{% endblock %}
views.py:
class Signup(View):
""" this class is used for user signup """
def get(self, request):
""" this function used to get the sign up form """
form = UserCreationForm()
return render(request, 'plant/signup.html', {'form': form})
def post(self, request):
""" this function used for post the sign up data """
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
class AuthLogin(View):
""" Its for login """
def get(self, request):
""" this function used to get the login form """
form = AuthenticationForm()
return render(request, 'plant/login.html', {'form': form})
def post(self, request):
""" this function used for post the login data """
form = AuthenticationForm(None, request.POST or None)
if form.is_valid():
login(request, form.get_user())
return redirect('/')
urls.py:
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name="plant/index.html")),
url(r'^logout/$', auth_views.logout,
{'next_page': 'login'}, name='logout'),
url(r'^login/$', core_views.AuthLogin.as_view(), name='login'),
url(r'^signup/$', core_views.Signup.as_view(), name='signup'),
]
In login page I should have the forget password link. When user will click on it, the reset password page will open and another one condition is after trying 3 wrong attempt the forget password button will be invisible for 1 hour.

Do not create this functionality yourself but use the built-in Django auth views. https://docs.djangoproject.com/en/1.11/topics/auth/default/#built-in-auth-views
The only thing you need to do is add the contrib auth urls to your project:
urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]
This gives you all views like login, logout, password reset etc.
If you want to customise the templates, copy the templates form /path/to/site-packages/django/contrib/admin/templates/registration/ to your app project/app/templates/registration/ and make any customisations
there.
If your app is listed before 'django.contrib.auth' in INSTALLED_APPS (it should always be like that) your custom templates will be picked first.

Related

Allow user to edit profile information and submit it causing page to redirect to profile page.

In django I am attempting to allow that user to edit his/her profile information, press submit, and have the the change reflect in his/her profile page.
This is the code :
In the views.py document in my application
User is allowed to view the profile page
def view_profile(request):
var = { 'user' : request.user }
return render(request, 'accounts/profile.html', var)
User is allowed to edit the profile page
def edit_profile(request):
if request.method == 'POST':
form = UserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('account/profile')
else:
form = UserChangeForm(instance=request.user)
var = {'form' : form }
return render(request, 'accounts/edit_profile.html', var)
This is the urls.py document
Import modules
from django.conf.urls import url
from . import views
Defined the urls
urlpatterns = [
url(r'^profile/$', views.view_profile, name = 'view_profile'),
url(r'^profile/edit/$', views.edit_profile, name = 'edit_profile')
]
This is the edit_profile
{% extends 'base.html' %}
{% block head %}
<title>{{ user }}</title>
{% endblock %}
{% block body %}
<div class = "container">
<form method = "post">
{% csrf_token %}
{{ form.as_p }}
<button class = "btn btn-default" type="submit">Submit</button>
</form>
</div>
{% endblock %}
When I edit user model on the edit_profile.html page and submit, it redirects
from :
http://127.0.0.1:8000/account/profile/edit/
To :
http://127.0.0.1:8000/account/profile/edit/account/profile
This latter urls is not accurate, it should redirect
To :
http://127.0.0.1:8000/account/profile
This is how that page looks
When you redirect you should include a leading slash to make it an absolute url:
return redirect('/account/profile')
You can avoid hardcoding the url by using the URL pattern name instead. The redirect shortcut will reverse the url for you:
return redirect('view_profile')

Why is that everytime I logout and then logged in again the pk becomes none in django

I always get this error:
Reverse for 'user_home' with arguments '()' and keyword arguments '{u'pk': None}' not found. 1 pattern(s) tried: ['ibs/(?P[0-9]+)/home/$']
in my template I can display my user.pk (it is equal to 1) but when i use it and pass it in my views i got the error above (pk: none). I have read some threads about this. Some are because of the url patterns but I changed and check my urls but nothing happened. Still gets the error.
this is my url:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^ibs/$', views.index, name='index'),
url(r'^ibs/register/$', views.user_add, name='user_add'),
url(r'^ibs/login/$', views.user_login, name='user_login'),
url(r'^ibs/(?P<pk>[0-9]+)/home/$', views.user_home, name='user_home'),
url(r'^ibs/(?P<user_pk>[0-9]+)/logout/$', views.user_logout, name='user_logout'),
url(r'^ibs/(?P<pk_item_add>[0-9]+)/additem/$', views.item_add, name='item_add'),
url(r'^ibs/(?P<pk_item>[0-9]+)/viewitem/(?P<pk_user>[0-9]+)/$', views.item_detail, name='item_detail'),
]
my template:
{% block home %}
<li class="active">Home</li>
{% endblock home %}
{% block register %}
{% endblock register %}
{% block login %}
{% endblock login %}
{% block logout %}
<li>
<a method="post" href="{% url "user_logout" user_pk=user.pk %}"><span class="glyphicon glyphicon-log-out"></span> Logout
</a>
</li>
{% endblock logout %}
{% block post %}
<li>
<a method="post" href="{% url "item_add" pk_item_add=user.pk %}"> {{user.pk}}
</a>
</li>
{% endblock post %}
def user_login(request):
if request.method == "POST":
#username is unique, get User where username is equal to requested username
username = User.objects.get(username = request.POST['username'])
if username.password == request.POST['password']:
request.session['username'] = username.id
return redirect('system.views.user_home', pk=username.id)
else:
return render(request, 'system/user_login.html')
views.py
def user_home(request, pk):
user = get_object_or_404(User, pk=pk)
try:
if request.session['username'] == user.pk:
items = Item.objects.all()
types = Type.objects.all()
return render(request, 'system/user_home.html', {'user':user, 'types':types,
'items': items})
else:
return redirect('system.views.user_login')
except KeyError:
return redirect('system.views.user_login')
def user_logout(request, user_pk):
user = get_object_or_404(User, pk=user_pk)
try:
del request.session['username']
return redirect('system.views.user_login')
except KeyError:
pass
return redirect('system.views.user_login')
Where did I go wrong? I passed all the necessary data from views to templates.
When a user is not logged in the user is likely the models.AnonymousUser which does not have a primary key.
https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#anonymous-users
If the user is not logged in then you probably don't want them to see that template at all. Redirect them to the login page in the view or check that the user is not anonymous in the template.

Redirecting after saving form on Django

I am working on extending the webapp we're left off with after completing the official Django Tutorial.
One of the functionalities I am looking to add is the ability for users to add polls themselves.
I am struggling with getting the page to process the data and then redirect to the index page ('/polls').
When I submit a new poll as a logged in user, I am returned to my index page, which is supposed to show most recently published polls, or in the event of no polls, the message "No polls are available."
For some reason, I always see "No polls are available", but once I click to the index page via a link on the site, it displays all of my polls, including my most recently created one, data intact!
Any thoughts here? I think I have included the relevant info below but happy to supply more. Thanks in advance for any help/advice.
views.py
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Poll.objects.order_by('-pub_date')[:15]
#login_required
def add_poll(request):
ChoiceFormSet = formset_factory(ChoiceForm, extra=3, min_num=2, validate_min=2)
if request.method == 'POST':
form = PollForm(request.POST)
formset = ChoiceFormSet(request.POST)
if all([form.is_valid(), formset.is_valid()]):
poll = form.save()
for inline_form in formset:
if inline_form.cleaned_data:
choice = inline_form.save(commit=False)
choice.question = poll
choice.save()
return render(request, 'polls/index.html', {})
else:
form = PollForm()
formset = ChoiceFormSet()
return render(request, 'polls/add_poll.html', {'form': form, 'formset': formset})
add_poll.html
{% extends 'polls/base.html' %}
{% block title %}Add Poll{% endblock %}
{% block body_block %}
<form role="form" id="poll_form" method="post" action="{% url 'polls:add_poll' %}">
<h2 class="form-signin-heading">Add a Poll</h2>
{% csrf_token %}
<table>
{{ form }}
{{ formset }}
</table>
<br/>
<button class="btn btn-primary" type="submit" name="submit">Create Poll</button>
</form>
{% endblock %}
index.html
{% extends 'polls/base.html' %}
{% block body_block %}
{% if latest_question_list %}
<ul>
{% for poll in latest_question_list %}
<li>{{ poll.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
{% endblock %}
urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^add_poll/$', views.add_poll, name='add_poll'),
url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
url(r'^profile_page/$', views.ProfileView.as_view(), name='profile_page'),
url(r'^edit_profile/$', views.edit_profile, name='edit_profile'),
)
When you save your form you are not redirecting.
Your are returning 'polls/index.html' with empty polls data, that's why you always get "No polls are available". But this is very incorrect, you must follow the Post/Redirect/Get (PRG) pattern, so instead of:
return render(request, 'polls/index.html', {})
do this:
return HttpResponseRedirect(reverse('polls:index'))
You don't do any redirect right now, you are just rendering your index template with an empty context (that's why you don't see anything). To redirect, you need to use HttpResponseRedirect when your form is valid.
So, please change line:
return render(request, 'polls/index.html', {})
(just over the else) to
return HttpResponseRedirect(reverse('index'))
I finally figured it out. I had to change my html form to this:
<form method="POST" action="{% url 'new_beam:beam_diagram' beam_id=1 %}" enctype="multipart/form-data">

Django - using generic login view not working

EDIT: the view now does log me in when I enter a correct username and password, but doesn't return any errors when I enter incorrect username and passwords.
I am using the generic login view provided by Django. This is my login.html template:
<body>
<h1>User Login</h1>
{% if form.has_errors %}
<p>Your username and password did not match.
Please try again.</p>
{% else %}
<form method="post" action=" . ">{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="hidden" name="next" value="/" />
<input type="submit" value="login" />
</form>
{% endif %}
</body>
Now, I am following the tutorial in the book called "Pact Publishing. Learning Website Development with Django". The view never returns
form.has_errors
even though I purposely submit an incorrect username and password. It just keeps returning me to the same page after I click submit. Also, according to the HTML book I read, it said that the 'action' attribute in the form is the URL of the page on the server that will retrieve the information. Is that why it isn't working? Because my
action=" . "
?
EDIT: the view is the generic login view:
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
request.session.set_test_cookie()
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
and my urls.py is just
url(r'^$', main_page),
url(r'^user/(\w+)/$', user_page),
url(r'^login/$', login),
Ah, found the answer over here:
form.has_errors tag not working
form.has_errors
was replaced with
form.errors
Try this.
Login.Html
<form action ="." method = POST>
{% csrf_token %}
{{ form.as_p }}
<input type = "submit" value = "login" class="btn">
</form>
urls.py
from django.contrib.auth.views import login, logout
from django.conf.urls import *
urlpatterns = patterns('',
url(r'login/',login,kwargs = {'template_name' : 'templates/auth/login.html'},
url(r'logout', logout,kwargs = {'template_name' : 'templates/auth/logout.html'}),
)
settings.py
LOGIN_REDIRECT_URL = '/dashboard'
LOGIN_URL = '/login/'

Django render_to_response not working as expected

Django 1.5 - django-ldap-auth
Trying to figure out how to properly using request_to_context as it only works on the login.html page itself. (user.is_authenticated etc).
After the user gets logged in, it forwards the user to /reboot. From there I want to use {{ user.is_authenticated }} / {{ user.username }}, but nothing shows up(true or false). It is just blank.
On the login.html page itself they work correctly. If I render to the reboot/index.html it does not render the code that I have the index do. I assumed I would be able to call these commands after a user is authenticated. Hopefully I am just missing a small piece to this puzzle.
I have included all of the necessary code. Let me know if you need something else.
Here is my layout.
reboot/form.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
class LoginForm(forms.Form):
username = forms.CharField(label=(u'User Name'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
views.py
from django.template import Context, loader, RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from servers.models import Server
from reboot.forms import LoginForm
import paramiko
import socket
def logout_user(request):
logout(request)
return HttpResponseRedirect('/status/')
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = Context( {
'servers': servers,
})
return HttpResponse(t.render(c))
def test_ssh_liveness(ssh, name):
try:
ssh.connect(name, timeout='1')
return True
except socket.timeout:
# server is down
return False
except socket.gaierror:
# invalid server name
return False
except paramiko.SSHException:
# unknown host key
return True
def server(request, name):
ssh = paramiko.SSHClient()
is_alive = test_ssh_liveness(ssh, name)
return HttpResponse("You selected server "+name+" and it is "+str(is_alive))
# user login
def login_user(request):
if request.user.is_authenticated():
# return HttpResponseRedirect('/reboot/')
pass
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect('/reboot/')
else:
return render_to_response('login.html', {'form', form}, context_instance=RequestContext(request))
else:
''' user is not submitting the form, show the login form '''
form = LoginForm()
context = {'form': form}
return render_to_response('login.html', context, context_instance=RequestContext(request))
reboot.urls
from django.conf.urls import patterns, url
from reboot import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
#(r'^$', views.login_user),
url(r'^server/(?P<name>[^/]+)', views.server, name='server')
)
main url file
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^reboot/', include('reboot.urls')),
# Login for reboot
(r'^login/$', 'reboot.views.login_user'),
(r'^logout/$', 'reboot.views.logout_user'),
url(r'^status/', include('status.urls')),
)
login.html
% extends "base.html" %}
{% block content %}
<p> print {{ user.is_authenticated }}</p>
<div id="login">
<form class="form-horizontal" name="LoginForm" action="/login/" method="post">
{% csrf_token %}
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<div class="control-group">
<label class="control-label" for="username">Username</label>
<div class="controls">
<input type="text" id="username" name="username" placeholder="Username">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="password" name="password" id="password" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class=controls">
<button type="submit" class="btn">Login</button>
</div>
</div>
</form>
</div>
{% endblock %}
/reboot/index.html
{% extends "base.html" %}
{% block title %}Server{% endblock %}
{% block content %}
<h2>Server Control Panel</h2>
<h4>Welcome, print {{ user.is_authenticated }}.</h4>
{% if user.is_authenticated %}<p>Logout</p>{% else %}Login</p>{% endif %}
<p class="lead">
The servers below correspond to servers that you have access to.
If you believe there are errors, please contact me.
</p>
<div class="container-fluid">
<table class="table table-hover">
<thead>
<tr>
<th><h4>Hostname</h4></th>
<th><h4>Commands</h4></th>
</tr>
</thead>
<tbody>
{% for server in servers %}
<tr>
<td>{{ server.hostname }}</td>
<td>
start
restart
shutdown
</td>
</tr>
{% endfor %}
</tbody>
</table>
</table>
</div>
{% endblock %}
I appreciate all of your help. I have been stuck on this issue for a few days now and have not been able to figure it out.
John
Your view needs a RequestContext instance (docs), like your login view, so it knows which user is logged in (and other stuff). So instead of:
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = Context( {
'servers': servers,
})
return HttpResponse(t.render(c))
just make it:
def index(request):
servers = Server.objects.all()
context = {
'servers': servers,
}
return render_to_response('reboot/index.html', context, context_instance=RequestContext(request))
EDIT
It's not really about the render_to_response. As the import says, that's just a shortcut.
Django's context processors (basically, functions that add variables to your template context) are request-based, and therefor are only called if you specify a RequestContext, and that includes django.contrib.auth.context_processors.auth, the context processor that includes the user variable into your template.
The equivalent of your code would be:
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = RequestContext(request, {
'servers': servers,
})
return HttpResponse(t.render(c))

Categories

Resources