I need help with a project in Django. In views.py I have created a login to the site including registration, but I need to somehow use models.py to edit and add more user parameters, which I don't think is possible in views. Can someone please help me with this. I am attaching the code below.
views.py
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib import messages
from django.shortcuts import redirect, render
from django.contrib.auth import authenticate, login, logout
from rocnikovka import settings
from django.core.mail import EmailMessage, send_mail
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.utils.http import urlsafe_base64_encode,urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from . tokens import generate_token
def home(request):
return render(request, "authentication/home.html")
def signup(request):
if request.method == "POST":
# username = request.POST.get("username")
username = request.POST["username"]
fname = request.POST["fname"]
lname = request.POST["lname"]
email = request.POST["email"]
pass1 = request.POST["pass1"]
pass2 = request.POST["pass2"]
if User.objects.filter(username=username):
messages.error(request, "Username already exist! Please try some other
username.")
return redirect("home")
if User.objects.filter(email=email).exists():
messages.error(request, "Email Address already registered! ")
return redirect("home")
if len(username)>20:
messages.error(request, "Username must be under 20 characters.")
return redirect('home')
if pass1 != pass2:
messages.error(request, "Passwords did not match")
return redirect('home')
if not username.isalnum():
messages.error(request, "Username must be Alpha-numeric!")
return redirect("home")
myuser = User.objects.create_user(username, email, pass1)
myuser.first_name = fname
myuser.last_name = lname
myuser.is_active = False
myuser.save()
messages.success(request,"Your account has been succesfully created. We have sent
you a confirmation email, please confirm your email in order to activate your
account. ")
# Welcome Email
subject = "Welcome to our games sites"
message="Hello " + myuser.first_name + "!! \n" + "Welcome to our games sites!! \n
Thank you for visiting our website \n we have also sent you a confirmation email,
please confirm your email address in order to activate your account, \n\n
Thanking you, \n Jiří Bezděkovský"
from_email = settings.EMAIL_HOST_USER
to_list = [myuser.email]
send_mail(subject, message, from_email,to_list,fail_silently=True )
# Email Address confirmation Email
current_site = get_current_site(request)
email_subject ="Confirm your email in games sites"
message2 = render_to_string('email_confirmation.html',{
'name': myuser.first_name,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(myuser.pk)),
'token': generate_token.make_token(myuser)
})
email = EmailMessage(
email_subject,
message2,
settings.EMAIL_HOST_USER,
[myuser.email],
)
email.fail_silently = True
email.send()
return redirect("signin")
return render(request, "authentication/signup.html")
def activate(request, uidb64, token):
try:
uid=force_str(urlsafe_base64_decode(uidb64))
myuser=User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
myuser=None
if myuser is not None and generate_token.check_token(myuser, token):
myuser.is_active = True
myuser.save()
login(request, myuser)
messages.success(request, "Your Account has been activated!!")
return redirect("signin")
else:
return render(request, "activation_failed.html")
def signin(request):
if request.method =="POST":
username = request.POST["username"]
pass1 = request.POST["pass1"]
user = authenticate(username=username, password=pass1)
if user is not None:
login(request, user)
fname = user.first_name
return render(request, "authentication/index.html", {"fname": fname})
else:
messages.error(request, "Bad Credentials!")
return redirect("home")
return render(request, "authentication/signin.html")
def signout(request):
logout(request)
messages.success(request, "Logged Out Successfully!")
return redirect("home")
# return render(request, "authentication/signout.html")
Related
Under my views I have all my views for user authentication which includes: signin, signup, signout and other function views.
views.py
from django.core.mail import EmailMessage,send_mail
from django.shortcuts import render,redirect
from django.contrib import messages
from django.contrib.auth import authenticate,login,logout
from my_site.settings import EMAIL_HOST_USER
from django.core.mail import send_mail
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.utils.http import urlsafe_base64_encode,urlsafe_base64_decode
from django.utils.encoding import force_bytes,force_str
from .tokens import generate_token
from .models import User
# Create your views here.
def all(request):
return render(request,'authentication/all_signups.html')
def signup(request):
if request.method == "POST":
username = request.POST.get("username")
fname = request.POST.get("fname")
lname = request.POST.get("lname")
email = request.POST.get("email")
password = request.POST.get("password")
password2 = request.POST.get("password2")
if User.objects.filter(username=username):
messages.error(request, "Username already exist!")
return redirect('home')
if User.objects.filter(email=email):
messages.error(request, "E-mail already exist!")
return redirect('home')
if len(username) > 15:
messages.error(request, "Length of username too long!")
return redirect('home')
if password != password2:
messages.error(request, "Passwords do not match!")
return redirect('home')
if not password.isalnum():
messages.error(request, "Password must be alphanumeric!")
return redirect('home')
user = User.objects.create_user(username=username,email=email,password=password)
user.fname = fname
user.is_active = False
user.save()
# Welcome E-mail
subject = 'Welcome to ADi meals mobile!'
message = f'Hello {fname.capitalize()}, welcome to ADi meals mobile!\n\nThank you for visiting our website.\n\nWe have also sent you a confirmation email, please confirm your email address to login into your account.\n\n\n\nThanking you.\n\n\nVictoria Oluwaseyi\nC.E.O'
from_email = EMAIL_HOST_USER
to_list = [user.email]
send_mail(subject,message,from_email,to_list,fail_silently=True)
#Email Confirmation
current_site = get_current_site(request)
email_subject = 'Confirm your email # ADi meals mobile!'
message2 = render_to_string('email_confirmation.html',{
'name':fname,
'domain':current_site.domain,
'uid':urlsafe_base64_encode(force_bytes(user.pk)),
'token': generate_token.make_token(user)
})
from_email2 = EMAIL_HOST_USER
to_list2 = [user.email]
#email = EmailMessage(
# email_subject,
# message2,
# from_email2,
# to_list2,
#)
#fail_silently = True
#email.send()
send_mail(email_subject,message2,from_email2,to_list2,fail_silently=True)
messages.success(request,"Your account has been successfully created!\nWe have also sent you a confirmation email, please confirm your email address to login into your account.")
return redirect('authentication:signin')
return render(request,'authentication/signup.html')
def signin(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user = authenticate(username=username,password=password)
if user is not None and user.is_active == False:
login(request, user)
messages.success(request, "You have successfully logged in")
fname = username
return render(request,'authentication/landing_page.html',{'fname':fname})
else:
messages.error(request,"Bad credentials! or Check your mail to verify account!")
return redirect('authentication:signin')
return render(request,'authentication/signin.html')
def signout(request):
logout(request)
messages.success(request, "You have successfully logged out!")
return redirect('home')
def activate(request, uidb64, token):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError,user.DoesNotExist):
user = None
if user is not None and generate_token.check_token(user, token):
user.is_active = True
fname = user.fname
user.save()
login(request, user)
messages.success(request, "Email has been verified successfully!")
return render(request,'authentication/landing_page.html',{'fname':fname})
else:
return render(request, 'activation_failed.html')
def account_info(request):
return render(request,'authentication/account_info.html',{'names':[request.user.username,request.user.first_name,request.user.last_name,request.user.email]})
def edit_account(request):
return render(request,'authentication/edit_account.html')
def setpassword(request):
return render(request,'authentication/setpassword.html')
Here is the html template I rendered to display the verification email message to the user.
email_confirmation.html
{% autoescape off %}
Welcome to ADi meals mobile!
Hello {{name | capfirst}},
Please confirm your email by clicking on the link below.
Confirmation link: http://{{domian}} Click me
{% endautoescape %}
You are sending the mail as Text, Emails default send in a text version and you need to use EmailMultiAlternatives to send an email in HTML format
from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template
subject = 'My Subject'
plaintext = get_template('email_templates/textmail_fallback.txt')
htmly = get_template('email_templates/htmlmail_prefered.html')
toList = ['test#mytest.com']
from_email = None
# from_email = 'MyDjangoSite#LocalHost'
# make email with text
msg = EmailMultiAlternatives(subject, plaintext.render(data), from_email, toList, reply_to=None, bcc=None, cc=None)
# Note: you can remove reply_to, bcc, cc, I'm just showing that those are options
# attach HTML email
msg.attach_alternative(htmly.render(data), 'text/html')
# send email
msg.send()
See: https://docs.djangoproject.com/en/4.1/topics/email/#sending-alternative-content-types
Edit!!
Note: you could also just change the type:
From the Docs, I missed it.
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
I think using the Alternative method is still the way to go, as it's more universal.
veiws.py
from django.shortcuts import render,redirect
from django.contrib.auth.models import User, auth
from django.contrib import messages
from travello.models import Destination
import traceback
from django.core.files.storage import FileSystemStorage
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request,user)
return redirect("/")
else:
messages.info(request,'invalid credentials')
return redirect('login')
else:
return render(request, 'login.html')
def register(request):
if request.method == "POST":
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
username = request.POST.get('username')
email = request.POST.get('email')
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
if password1 == password2:
if User.objects.filter(username=username).exists():
messages.info(request,'Username taken')
return redirect('register')
elif User.objects.filter(email=email).exists():
messages.info(request,'EMAIL taken')
return redirect('register')
else:
user = User.objects.create_user(username=username, email=email, password=password1, first_name=first_name, last_name=last_name)
user.save();
print("User created")
return redirect('login')
else:
messages.info(request,'password not matching...')
return redirect('register')
else :
return render(request, 'register.html')
def logout(request):
auth.logout(request)
return redirect('/')
def postdestination(request):
if request.method == 'POST':
try:
f = request.FILES["img"]
fs = FileSystemStorage()
filename = fs.save(f.name, f)
uploaded_file_url = fs.url(filename)
name = request.POST['name']
# img = request.POST['img']
description = request.POST['description']
price = request.POST['price']
offer = request.POST.get('offer')
if offer == "on":
offer = True
else:
offer = False
d = Destination.objects.create(name=name, desc=description,img=uploaded_file_url,price=price,offer=offer)
d.save()
except Exception as e:
traceback.print_exc()
return redirect('/')
else:
return render(request, 'post_destination.html')
While registering this error is occurring. I'm using postgresql as DBMS .
Request Method: POST
Request URL: http://localhost:8000/accounts/register
Django Version: 3.2
Exception Type: ValueError
ValueError at /accounts/register
The given username must be set
You are using request.POST but you are not passing any form to it after.
You should explicitly pass the form in the different requests so that django will know what to handle.
I am developing a feature, when a user registers it automatically logs the user in
but i get 'AnonymousUser' object has no attribute '_meta' error.
but when i use the same code to login the user it works fine.
my forms.py:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User
from .models import *
class RegisterForm(forms.Form):
fname = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"fname entry", "placeholder":"First Name"}), required=True)
lname = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"lname entry", "placeholder":"Last Name"}), required=True)
phone = forms.CharField(error_messages=(), widget=forms.TextInput(attrs={"class":"phone entry", "placeholder":"Phone Number"}), required=True)
password = forms.CharField(widget=forms.PasswordInput(attrs={"class":"password entry", "placeholder":"Password", "autocomplete":"off"}), required=True)
password2 = forms.CharField(widget=forms.PasswordInput(attrs={"class":"password entry", "placeholder":"Confirm Password", "autocomplete":"off"}), required=True)
def clean(self, *args, **kwargs):
fname = self.cleaned_data.get("fname")
lname = self.cleaned_data.get("lname")
phone = self.cleaned_data.get("phone")
password = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password2")
if phone and password and fname and lname and password2:
try:
user = User.objects.get(phone=PhoneNumber.objects.get(number=phone))
if user:
raise forms.ValidationError("user exists login instead")
except ObjectDoesNotExist:
pass
if password!=password2:
raise forms.ValidationError("passwords didn't match")
else:
if len(password)<8:
raise forms.ValidationError("short password! password should be longer than 8")
in my forms i have a registration form which does not inherit from django's user creation form.
my views.py:
def registerView(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
fname = form.cleaned_data.get("fname")
lname = form.cleaned_data.get("lname")
username = generate_username(fname, lname)
phone = form.cleaned_data.get("phone")
u = User.objects.create_user(email="", first_name=fname, last_name=lname, username=username, is_active=False)
u.set_password(form.cleaned_data.get("password"))
u.save()
p = PhoneNumber(user=u, number=phone)
p.save()
phone = PhoneNumber.objects.get(number=phone)
u = User.objects.get(phone=phone)
userLogin = authenticate(username=username, password=u.password)
login(request, userLogin)
return redirect('home')
else:
form = RegisterForm()
return render(request, 'main/register.html', {'form':form})
my loginView:
def loginView(request):
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
phone = PhoneNumber.objects.get(number=form.cleaned_data.get('phone'))
u = User.objects.get(phone=phone)
user = authenticate(username=u.username, password=form.cleaned_data.get('password'))
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
print('success')
return redirect('home')
else:
form = LoginForm()
return render(request, 'main/login.html', {'form':form})
i have imported everything i need. the same code works with the loginView function but it doesn't work on registerView
What should i do to fix this?
You have this line in your view:
userLogin = authenticate(username=username, password=u.password)
The point to be noted here is that u is an instance of the user model and u.password will give the hashed password while authenticate expects it to be a raw password and hence returns None. In fact you don't even need to use authenticate while registering as you already have the user instance:
def registerView(request):
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
fname = form.cleaned_data.get("fname")
lname = form.cleaned_data.get("lname")
username = generate_username(fname, lname)
phone = form.cleaned_data.get("phone")
# removed `is_active=False` as per comment by #Nahu Gere
user = User.objects.create_user(email="", first_name=fname, last_name=lname, username=username) # better variable name
user.set_password(form.cleaned_data.get("password"))
user.save()
phone = PhoneNumber(user=user, number=phone)
phone.save()
login(request, user) # Directly use saved user instance
return redirect('home')
else:
form = RegisterForm()
return render(request, 'main/register.html', {'form':form})
I got this error because In my register view, I had this code:
user.is_active = False
user.save()
then I had so the user got logged in automatically after registering an account.
user = authenticate(username=user.username, password=raw_password)
login(request, user)
I solved it by commenting out the auto login
# user = authenticate(username=user.username, password=raw_password)
# login(request, user)
i am trying to add to my messages.success the username so when he login the message go up and have the username
views.py:
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username and password:
user = authenticate(username=username, password=password)
if user is not None:
l_login(request, user)
success_url = '/home'
messages.success(request, 'You logged in to ')
return redirect('home')
else:
messages.error(request, 'Username or Password is Incorrect')
else:
messages.error(request, 'Fill out all the Fields Please')
return render(request, 'register/login.html',{})
You can obtain this from the user object:
messages.success(request, f'You logged in to {user.username}')
The f'…' is literal string interpolation [pep-498].
I'm using the normal development server for Django and i am building a simple app.
A user should be able to log in and change his email and password.
To understand the django system better, I decided to write the views and such myself, only using the contrib.auth library.
Now to the problem:
Once a user logs in and changes his password, he cannot login again, unless he logs into the standard django admin page before.
Here is my code:
the views.py
def login(request):
print("test")
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
return HttpResponseRedirect('/accountManagement/home')
else:
form = LoginForm()
else:
HttpResponse("form is not valid")
else:
form = LoginForm()
return render(request, 'accountManagement/login.html', {'form': form})
def home(request):
print(request.user.username)
if request.user.is_authenticated:
passwordForm = ChangePasswordForm()
emailForm = ChangeEmailForm()
return render(request, 'accountManagement/home.html', {'passwordForm': passwordForm, 'emailForm': emailForm})
else:
return HttpResponseRedirect("/accountManagement/")
def change_password(request):
if request.user.is_authenticated:
if request.method == 'POST':
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation = passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation) and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")
else:
return HttpResponse("request != POST")
else:
return HttpResponse("user ist not authenticated")
url.py:
urlpatterns = [
url(r'^$', views.login, name='login'),
url(r'^home', views.home, name='home'),
url(r'^changeEmail', views.change_email, name='changeEmail'),
url(r'^changePassword', views.change_password, name='changePassword'),
url(r'^logout', views.logout_view, name='logout'),
]
the forms:
class LoginForm(forms.Form):
username = forms.CharField(label='Username', max_length=20)
password = forms.CharField(label='Password', max_length=20)
class ChangeEmailForm(forms.Form):
newEmail = forms.CharField(label='New Email', max_length=50)
class ChangePasswordForm(forms.Form):
oldPassword = forms.CharField(label='Old Password', max_length=20)
newPassword = forms.CharField(label='New Password', max_length=20)
newPasswordConfirmation = forms.CharField(label='Confirm new Password', max_length=20)
Thanks for the help, really can't figure this one out.
Changing password destroy user authentication status, so you need re-authenticate him with new password again:
from django.contrib.auth import login
def change_password(request):
if request.user.is_authenticated:
if request.method == 'POST':
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation =
passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation)\
and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
# Re-authentication ===============================
# =================================================
user = authenticate(username=request.user.username,
password=NewPassword)
login(request, user)
# Why redirect to logout?!
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")
else:
return HttpResponse("request != POST")
else:
return HttpResponse("user ist not authenticated")
Also I suggest you use CBV (Class based views) instead FBV (Function based views).
Any case you can use decorators #login_required and #require_http_methods in your view to remove is_authenticated and method != 'POST' logic.
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
#require_http_methods(["POST", ])
#login_required(redirect_field_name='my_redirect_field')
def change_password(request):
passwordForm = ChangePasswordForm(request.POST)
if passwordForm.is_valid():
oldPassword = passwordForm.cleaned_data['oldPassword']
newPassword = passwordForm.cleaned_data['newPassword']
newPasswordConfirmation =
passwordForm.cleaned_data['newPasswordConfirmation']
if (newPassword == newPasswordConfirmation)\
and (request.user.check_password(oldPassword)):
request.user.set_password(newPassword)
request.user.save()
# Re-authentication ===============================
# =================================================
user = authenticate(username=request.user.username,
password=NewPassword)
login(request, user)
# Why redirect to logout?!
return HttpResponseRedirect("/accountManagement/logout")
else:
return HttpResponse("password change failed")
else:
return HttpResponse("password form not valid")