Django. Сheck activation code - django

UPDATE!
The activation code is stored in the database, but I can not call it as a function of activation
Gives an error message:
TypeError at /account/activation/18d2ecbee1fd15440bbcfdf942c071a2f5b8d0ff/
activation() got an unexpected keyword argument 'activation_key'
forms.py
from django import forms
from django.contrib.auth.models import User
class EmailForm(forms.Form):
email = forms.EmailField(widget=forms.EmailInput(
attrs={'class': 'form-control input-lg',
'placeholder': 'Ваш E-mail'}))
views.py
import datetime
import hashlib
import random
from django.conf import settings
from django.contrib.auth import authenticate, logout, login
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.http import HttpResponseRedirect, HttpResponse
from django.http import Http404
from django.shortcuts import render
from forms import *
from models import *
def register(request):
if request.method == "POST":
form = EmailForm(request.POST)
if form.is_valid():
form_email = form.cleaned_data['email']
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
activation_key = hashlib.sha1(salt+form_email).hexdigest()
key_expires = datetime.datetime.today() + datetime.timedelta(2)
subject = 'Activation your e-mail'
from_email = settings.EMAIL_HOST_USER
to_email = [form_email]
message_email = "Hi, i'm link activate e-mail! \
http://127.0.0.1:8000/account/activation/%s" % activation_key
send_mail(subject,
message_email,
from_email,
to_email,
fail_silently=True)
code = ActivationEmail.objects.create(activation_key=activation_key)
code.save()
return render(request, 'registration/activate.html', locals())
else:
form = EmailForm()
return render(request, 'registration/register.html', locals())
def activation(request, code):
try:
active = ActivationEmail.objects.get(activation_key=code)
except ActivationEmail.DoesNotExist:
active = None
active.validated = True
if not active:
raise Http404
print "USER WAS HERE?!"
return HttpResponseRedirect('/account/wizard/')
urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^register/', views.register, name='registration'),
url(r'^activation/(?P<activation_key>\w+)/', views.activation, name='activation'),
url(r'^login/$', views.user_login, name='login'),
url(r'^logout/$', views.user_logout, name='logout'),
Just can not figure out how to do next; (

You will need to
1- You will need to create a new table to store the activation keys, such that you can create a new entry before sending the email
2.- On the user clicking the activation link, that link should be sufficient for you to find the record you created before sending the email
3.- If everything matches, then set a user.is_active type thing on your user model.
But all that said, you are reinventing the wheel here. There are several top notch packages you can use with this and more. I would recommend django-allauth with also give you social login support (e.g. facebook). If you just want the activation portion, there is an older package called django-registration. There are a few others if you search around, but the point is you don't need to implement this (and you probably don't want to mess around with registration if you are not an expert)

Related

Django Create a user using only Email and set as inactive

In my app I have 3 kind of users with different permissions. HR, Employees and candidate.
I would like to be able to create a User employee providing only its email ans set it as inactive And when the employee sign in into the app he setup a his first name, last name and a password and become Active on the app
I am starting in django and have really no idea how to do it;
I started the authentication process using the documentation and I get to :
views.py :
from django.shortcuts import render
from .forms import HRForm, CandidateForm, EmployeeForm
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.backends import ModelBackend
from .models import MyUser
def registerEmployee(request):
registered = False
if request.method == "POST":
Employee_form = EmployeeForm(data=request.POST)
if Employee_form.is_valid():
user = Employee_form.save()
user.set_password(user.password)
user.is_employee = True
user.save()
registered = True
else:
print("Error!")
else:
Employee_form = EmployeeForm()
return render(request,'Employee_registration_form.html',
{'Employee_form':Employee_form,
'registered':registered})
Could you please help me or give me direction to dive in ?
Thx you ;)
For activating/deactivating a user you could use:
user.is_active = False/True
For creating the user I recommend the following article:
https://medium.com/#ramykhuffash/django-authentication-with-just-an-email-and-password-no-username-required-33e47976b517

User matching query does not exist - django

I have a page which shows the user and their about. And in that, there's a link to update their about. But when I open that link it shows me with this error:
DoesNotExist at /profile/user/update_about/
User matching query does not exist.
And the traceback hightlights this line, which from the profile method in the views:
13. user = User.objects.get(username=unquote(user_name))
However this error does not occur when I load the profile method. It occurs only on the update_profile method in the views.
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from urllib import unquote
from django.contrib.auth.models import User
from models import About
from forms import AboutForm
# Create your views here.
def profile(request, user_name):
user = User.objects.get(username=unquote(user_name))
about = About.objects.get_or_create(user=user)
about = about[0]
return render(request, 'user_profile.html', {
'user':user,
'about_user':about
})
def update_about(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method == 'POST':
form = AboutForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
about = About.objects.get(user=user)
form = AboutForm(initial={'dob':about.dob})
return render(request, 'update_about.html',{
'form':form
})
urls.py
urlpatterns = patterns('',
# Examples:
url(r'(?P<user_name>[\w#%.]+)/$', 'user_related.views.profile', name='profile'),
url(r'(?P<user_name>[\w#%.]+)/update_about/$', 'user_related.views.update_about', name='update_about'),
What is causing this? Your help will be very much appreciated. Thank you.
You forgot to add the caret sign (^) at the first position of regex. So the first regex matched "update_about/" part of the url.
Fixed code:
url(r'^(?P<user_name>[\w#%.]+)/$', 'user_related.views.profile', name='profile'),
url(r'^(?P<user_name>[\w#%.]+)/update_about/$', 'user_related.views.update_about', name='update_about'),

Creating Django sessions

I am facing a problem while building a Django web app.
I want that if a user logs into his account, his session should be stored and when he agains visits the login page ,he should be redirected to his home page. I have tried using
Here is my code.
Views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.template import RequestContext
def index(request):
return HttpResponse("Index Page")
#login_required
def home(request):
ctx = {}
return render_to_response('auth/home.html',ctx, context_instance = RequestContext(request))
Urls.py
from django.conf.urls.defaults import *
from django.contrib.auth.views import login, logout
urlpatterns = patterns('',
url(r'^$','apps.auth.views.index'),
)
urlpatterns = patterns('',
url(r'cc/', login, kwargs = {'template_name' : 'auth/cc.html'} , name = 'cc_login'),
url(r'logout/', logout, name = 'cc_logout'),
url(r'home/','apps.auth.views.home', name = 'cc_home'),
)
I ran into the same situation with my django project.
I solved it by making a view that was similar too:
def login_page(request):
if request.user.is_authenticated():
return redirect(<insert your desired page here>)
else:
return render(<whatever the login page is>)
This way, if the user is logged in, they will be redirected to whatever page you want them to be.
EDIT:
In response to the comments below, I am modifying my answer (original is still above).
Here is what I have done to solve your problem.
from django.contrib.auth.views import login
def custom_login(request, **kwargs):
"""
Redirects the user to the desired page if they are authenticated
"""
if request.user.is_authenticated():
return redirect(<whatever page or view you want them to go to>)
else:
return login(request, **kwargs)
For example, your kwargs could be {'template_name': 'your_login_template.html', 'authentication_form': YourCustomRegistrationFormClass}
If you're using the standard login and registration procedures, just leave the kwargs part blank.
I'm fairly new to Django, but have you tried overriding the default login view?
views.py
from django.contrib.auth import views as auth_views
from django.shortcuts import redirect
def login(request, *args, **kwargs):
if request.method == 'POST':
request.session.set_expiry(0) # Remember user session
if request.user.is_authenticated():
return redirect(USER_PAGE_ADDRESS)
return auth_views.login(request, *args, **kwargs)
urls.py
urlpatterns = patterns('',
url(r'cc/', APP_NAME.views.login, kwargs = {'template_name' : 'auth/cc.html'} , name = 'cc_login'),
...
)

Login URL using authentication information in Django

I'm working on a platform for online labs registration for my university.
Login View [project views.py]
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib import auth
def index(request):
return render_to_response('index.html', {}, context_instance = RequestContext(request))
def login(request):
if request.method == "POST":
post = request.POST.copy()
if post.has_key('username') and post.has_key('password'):
usr = post['username']
pwd = post['password']
user = auth.authenticate(username=usr, password=pwd)
if user is not None and user.is_active:
auth.login(request, user)
if user.get_profile().is_teacher:
return HttpResponseRedirect('/teachers/'+user.username+'/')
else:
return HttpResponseRedirect('/students/'+user.username+'/')
else:
return render_to_response('index.html', {'msg': 'You don\'t belong here.'}, context_instance = RequestContext(request)
return render_to_response('login.html', {}, context_instance = RequestContext(request))
def logout(request):
auth.logout(request)
return render_to_response('index.html', {}, context_instance = RequestContext(request))
URLS
#========== PROJECT URLS ==========#
urlpatterns = patterns('',
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),
(r'^admin/', include(admin.site.urls)),
(r'^teachers/', include('diogenis.teachers.urls')),
(r'^students/', include('diogenis.students.urls')),
(r'^login/', login),
(r'^logout/', logout),
(r'^$', index),
)
#========== TEACHERS APP URLS ==========#
urlpatterns = patterns('',
(r'^(?P<username>\w{0,50})/', labs),
)
The login view basically checks whether the logged in user is_teacher [UserProfile attribute via get_profile()] and redirects the user to his profile.
Labs View [teachers app views.py]
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import User
from accounts.models import *
from labs.models import *
def user_is_teacher(user):
return user.is_authenticated() and user.get_profile().is_teacher
#user_passes_test(user_is_teacher, login_url="/login/")
def labs(request, username):
q1 = User.objects.get(username=username)
q2 = u'%s %s' % (q1.last_name, q1.first_name)
q2 = Teacher.objects.get(name=q2)
results = TeacherToLab.objects.filter(teacher=q2)
return render_to_response('teachers/labs.html', {'results': results}, context_instance = RequestContext(request))
I'm using #user_passes_test decorator for checking whether the authenticated user has the permission to use this view [labs view].
The problem I'm having with the current logic is that once Django authenticates a teacher user he has access to all teachers profiles basically by typing the teachers username in the url.
Once a teacher finds a co-worker's username he has direct access to his data.
Any suggestions would be much appreciated.
A simple way would be to modify the view to add an extra check:
#user_passes_test(user_is_teacher, login_url="/login/")
def labs(request, username):
if username != request.user.username:
return HttpResponseNotAllowed()
... and so on ...
Assuming you have a variable called 'teacher' that represents the profile of the teacher whose profile you're viewing, just do something like this early in the view:
if request.user.get_profile() != teacher:
..redirect, throw 404, whatever you fancy
Just a short hint.
...
user = request.user
enrollment = get_object_or_404(Enrollment, id=enrollment_id)
profile = get_object_or_404(Profile, user=user)
if not (enrollment.profile == profile or user.is_staff):
raise Http404
...
enrollment.delete()
We used such if statements to determine, whether the actual user and the action he requested match. In the example above, only the profile who create an enrollment is allowed to delete it (or someone with staff priviledges).

django LOGIN_REDIRECT_URL with dynamic value

I'm trying to redirect a user to a url containing his username (like http://domain/username/), and trying to figure out how to do this. I'm using django.contrib.auth for my user management, so I've tried using LOGIN_REDIRECT_URL in the settings:
LOGIN_REDIRECT_URL = '/%s/' % request.user.username # <--- fail..
but it only seems to accept fixed strings, rather than something that'll be determined after the user is logged in. How can I still accomplish this?
A solution, is to redirect to a static route like '/userpage/' and have that redirect to the final dynamic page.
But I think the real solution is to make a new view that does what you really want.
from django.contrib.auth import authenticate, login
from django.http import HttpResponseRedirect
def my_view(request):
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)
HttpResponseRedirect('/%s/'%username)
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.
http://docs.djangoproject.com/en/dev/topics/auth/#authentication-in-web-requests
for more information about rewriting the view. This is how the docs say to override this kind of thing.
With the class-based django.contrib.auth.views.LoginView, you can now simply override get_success_url:
urls.py:
url(r'^login$', MyLoginView.as_view(), name='login'),
url(r'^users/(?P<username>[a-zA-Z0-9]+)$', MyAccountView.as_view(), name='my_account'),
views.py
class MyLoginView(LoginView):
def get_success_url(self):
return reverse('my_account', args=[self.request.user.username])
Wrap the auth view in your own custom view and redirect to wherever you want if authentication succeeded.
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.urlresolvers import reverse
def login(request):
template_response = auth.views.login(request)
if isinstance(template_response, HttpResponseRedirect) and template_response.url == '/accounts/profile/':
return HttpResponseRedirect(reverse('user', args=(request.user.username,)))
return template_response
Another alternative is to use the query param next to indicate where to redirect to after the login.
sign in
I use django-two-factor-auth login view which provides OTP features for login.
Hence I extend from two_factor's LoginView.
In main urls.py:
from two_factor.urls import urlpatterns as tf_urls
urlpatterns = [
# make sure login is before default two_factor (tf_urls) urls
# coz first url has higher preference
path('account/login/', MyLoginView.as_view(), name='login'),
path('', include(tf_urls)),
]
In views.py:
from two_factor.views.core import LoginView
from two_factor.utils import default_device
class MyLoginView(LoginView):
def get_success_url(self):
if self.is_otp_setup() is True:
return reverse('homepage:homepage')
# otp not setup. redirect to OTP setup page
else:
return reverse('two_factor:setup')
def is_otp_setup(self):
if self.request.user and \
self.request.user.is_authenticated and \
default_device(self.request.user):
return True
else:
return False