Django DeleteView Not Saving Changes - python-3.x

I'm using django DeleteView to delete user account. when i set the user's is_active property to False, it doesn't get saved in the database. it's still set to True
here's my views.py
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from django.http import HttpResponseRedirect
from django.views.generic.edit import DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
class DeleteAccount(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
"""
DeleteAccount: view to delete user account
"""
model = User
template_name = 'registration/delete_account.html'
success_url = reverse_lazy('core:index')
success_message = 'Account Successfully Deleted!'
def form_valid(self, form):
"""
Delete account and logout current user
"""
account = self.get_object()
# verify if user is the rightful owner of this account
if not account.id == self.request.user.id:
return HttpResponseRedirect(reverse_lazy('accounts:index'))
account.is_active = False # DOESN'T GET SAVED
account.save() # EVEN AFTER CALLING MODEL.SAVE() METHOD
logout(self.request)
return super().form_valid(form)
def get_object(self):
return get_object_or_404(User, pk = self.request.user.id)

Related

Get the following error while submitting a form: RelatedObjectDoesNotExist at /agents/create/ User has no userprofile

I'm working on a project and get the following error: RelatedObjectDoesNotExist at /agents/create/
User has no userprofile.I created a form for the user to submit an Agent but when I create an Agent using the form it gives me the above mentioned error but when I try to submit an already created agent it says User with that name already exists.I have two apps Agents and Leads Here is my code:
agents/views.py
from django.shortcuts import reverse
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from leads.models import Agent
from .forms import CreateAgentForm
class AgentListView(LoginRequiredMixin, generic.ListView):
template_name = 'agents/agent_list.html'
def get_queryset(self):
return Agent.objects.all()
class CreateAgentView(LoginRequiredMixin, generic.CreateView):
template_name = 'agents/agent_create.html'
form_class = CreateAgentForm
def get_success_url(self):
return reverse('agent-list')
def form_valid(self, form):
agent = form.save(commit=False)
agent.userprofile = self.request.user.userprofile
agent.save()
return super(CreateAgentView, self).form_valid(form)
leads/models.py
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class Lead(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
age = models.IntegerField(default=0)
agent = models.ForeignKey('Agent', on_delete=models.CASCADE)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Agent(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
userprofile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
def __str__(self):
return self.user.first_name
def post_user_profile(instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(post_user_profile, sender=User)
agents/urls.py
from django.urls import path
from .views import AgentListView, CreateAgentView
urlpatterns = [
path('', AgentListView.as_view(), name='agent-list'),
path('create/', CreateAgentView.as_view(), name='agent-create'),
]
agents/forms.py
from django import forms
from leads.models import Agent
class CreateAgentForm(forms.ModelForm):
class Meta:
model = Agent
fields = ('user',)
I'm still learning so any help would be appreciated.
I think the admin user has no user profile created, so you need to manually create one for him in the admin panel since migrations have already been done.
Erase your db and redo a migration.
Create User with the admin panel

NOT NULL constraint failed: jobs_job.created_by_id IntegrityError at /jobs/add/

I am trying to enable the user to be able to add job and after filling the form i got that error. Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
class Job(models.Model):
title = models.CharField(max_length=255)
short_description = models.TextField()
long_description = models.TextField(blank=True, null=True)
created_by = models.ForeignKey(User, related_name='jobs', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import AddJobForm
from .models import Job
def job_detail(request, job_id):
job = Job.objects.get(pk=job_id)
return render(request, 'jobs/job_detail.html', {'job': job})
#login_required
def add_job(request):
if request.method == 'POST':
form = AddJobForm(request.POST)
if form.is_valid():
job = form.save(commit=True)
job.created_by = request.user
job.save()
return redirect('dashboard')
else:
form = AddJobForm()
return render(request, 'jobs/add_job.html', {'form': form})
forms.py
from django import forms
from .models import Job
class AddJobForm(forms.ModelForm):
class Meta:
model = Job
fields = ['title','short_description','long_description']
What do i need to do to solve this error? I have try to remove the commit=True, from views.py and I have try to remove sqlite3 and do the migrations again.
You are trying to save the object without a value for created_by (hence the error message), then assign a value for that field and save again. You should change
job = form.save(commit=True)
to
job = form.save(commit=False)
so that the first .save doesn't actually try to commit anything to the database. It is simply used to construct the Job instance so that you can complete any missing values and actually save it using job.save().
Note that if you omit the commit= argument it is assumed to be True.

Django custom login issue

I have created a custom authenticate method because instead of username I want to log in through email for that I have written backends.py
backends.py
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
UserModel = get_user_model()
class EmailBackend(object):
def authenticate(username=None,password=None):
try:
user = UserModel.objects.get(email=username)
if user.check_password(password):
return user
else:
return None
except UserModel.DoesNotExist:
raise ValidationError('Invalid Credentials')
def get_user(self,user_id):
try:
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
After authenticating i want user to be logged in.For that i am using login method as below:
login(request,user,backend='django.contrib.auth.backends.ModelBackend')
views.py
from django.shortcuts import render,redirect
from users.forms import RegisterForm,LoginForm
from users.backends import EmailBackend as em
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login
def register(request):
if request.method=='POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
print('Successfully Created')
else:
form = RegisterForm()
return render(request,'users/register.html',{'form':form})
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
uname = request.POST['username']
pwd = request.POST['password']
user = em.authenticate(username=uname,password=pwd)
if user is not None:
if user.is_active==True:
k=login(request,user,backend='django.contrib.auth.backends.ModelBackend')
print(user,k)
print('Successfull login')
else:
print('Unsuccessfull login')
else:
form = LoginForm()
return render(request,'users/login.html',{'form':form})
In my console, I am trying to get the value returned by the login function but that is returning None .
k=login(request,user,backend='django.contrib.auth.backends.ModelBackend')
print(user,k)
Output in my console:
[16/Mar/2021 16:02:34] "POST /register/ HTTP/1.1" 200 881
[16/Mar/2021 16:02:52] "GET /login/ HTTP/1.1" 200 705
testuser#gmail.com None
Successfull login
[16/Mar/2021 16:02:58] "POST /login/ HTTP/1.1" 302 0
[16/Mar/2021 16:02:58] "GET /home HTTP/1.1" 200 237**
Print method is giving the correct value of user but for k it is giving None. That means the login function is not working and that means login authentication is not working properly.
How can I do login once authenticate method is returned, user? In which way login can be successful.
My code:
settings.py
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend',
'users.backends.EmailBackend']
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,AbstractUser
from django.utils.translation import gettext_lazy as _
class CustomUser(AbstractBaseUser):
email = models.EmailField(_('email address'), unique=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
USERNAME_FIELD='email'
forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django import forms
from users.models import CustomUser
class RegisterForm(UserCreationForm):
class Meta():
model = get_user_model()
fields = ('email', 'password1', 'password2')
class LoginForm(AuthenticationForm):
class Meta():
model = get_user_model()
You are doing you login wrong. You are referencing the auth Backend you just overwrote.
In your login function, do
login(request, user)
And in your settings
AUTHENTICATION_BACKENDS = ['users.backends.EmailBackend', 'django.contrib.auth.backends.ModelBackend']
One more thing, do not import your backend. Just import django authenticate module like you would do if weren't having your own backend
And change your authenticate line to
From django.contrib.auth import authenticate
user = authenticate(username=uname, password=pwd)
I got the answer login method has no return value that's why it is returning None. Once authenticate method is executed it will return a user if credentials are valid . After that login method will make you logged in.

Creating User class with Flask-login and PyMongo and retrieving data from MongoDB

Hi guys,
I'm a total noob regarding Python and Flaks. As part of my school project, I need to create user registration/login functionality with Flask and PyMongo.
So basically register a user with the username, email, and user password.
Login user with email and password.
Retrieve from MongoDb user default profile image following with profile date created, user username, and user email.
The way we need to do this is to create a User class.
When a user is successfully login they should see displayed on the front-end their username, email, default profile image, and date when the user profile was created.
Then the user needs to have an option to upload their profile image, username, and email.
Unfortunately, it has to be MongoDB for the database.
My current code is not uploading the User class blueprint to MongoDB and I don't know how to upload the default image and retrieve user info in the profile.html
Can you help me with this, please?
Any useful advice is welcome and if you can fix my code that would be great.
If you need more info let me know.
MY CODE SO FAR:
routes.py
import os
import json
from flask import Flask, flash, render_template, redirect, request, session, url_for
from flask_sqlalchemy import SQLAlchemy
from mongoengine import *
from datetime import datetime
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from werkzeug.urls import url_parse
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager
from flask_login import current_user, login_user, logout_user, login_required
from forms import RegisterForm, LoginForm, AddTip, UpdateProfile
if os.path.exists("env.py"):
import env
app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get("MONGO_DBNAME")
app.config["MONGO_URI"] = os.environ.get("MONGO_URI")
connect("MONGO_DBNAME", host=app.config["MONGO_URI"])
app.secret_key = os.environ.get("SECRET_KEY")
mongo = PyMongo(app)
login = LoginManager(app)
login.login_view = 'login'
login.login_message = "To access your profile, pleas log in!"
login.login_message_category = "log-info"
class User(Document):
username = StringField(unique=True, required=True)
email = EmailField(unique=True)
password = BinaryField(required=True)
age = IntField()
profile_image = ImageField()
registered = BooleanField(default=False)
date_created = DateTimeField(default=datetime.utcnow)
def __init__(self, username, email, date_created):
self.username = username
self.email = email
self.date_created = date_created
#staticmethod
def is_authenticated():
return True
#staticmethod
def is_active():
return True
#staticmethod
def is_anonymous():
return False
def get_id(self):
return self.username
#staticmethod
def check_password(password_hash, password):
return check_password_hash(password_hash, password)
#login.user_loader
def load_user(username):
user = mongo.db.users.find_one({"username": username})
if not user:
return None
return User(user["username"], user["email"], user["date_created"])
THEN MY REGISTER ROUTE:
#app.route("/registration", methods=["GET", "POST"])
def registration():
form = RegisterForm()
if form.validate_on_submit():
user = {
"username" : request.form.get("username").lower(),
"email" : request.form.get("email"),
"password" : generate_password_hash(request.form.get("password"))
}
mongo.db.users.insert_one(user)
session["user"] = request.form.get("username").lower()
flash("Welcome to your new profile", "reg-success")
return redirect(url_for("profile", username=session["user"]))
return render_template("registration.html", title="| Register", form=form)
LOG IN ROUTE:
#app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return redirect(url_for("home"))
form = LoginForm()
if form.validate_on_submit():
user = mongo.db.users.find_one({"email": form.email.data})
if user and User.check_password(user["password"], form.password.data):
user_obj = User(username=user["username"])
login_user(user_obj)
next_page = request.args.get("next")
return redirect(next_page) if next_page else redirect(url_for("profile"))
else:
flash("Invalid username or password", "reg-danger")
return render_template("login.html", title="| Login", form=form)
PROFILE ROUTE:
#app.route("/profile", methods=["GET", "POST"])
#login_required
def profile():
form = UpdateProfile()
if form.validate_on_submit():
flash("Your details are updated", "reg-success")
else:
flash("Pleas check your details", "reg-danger")
return render_template('profile.html', title='| Profile', form=form)

Im not receiving the email verification in order to activate the user created

Please I've created an authentication system where a user can login with both username and email address.
The account is deactivated when it is created. I want the user to confirm his email before the account is
activated. I used the django email verification but although the user is created successfully, I dont receive
the email. Please help.
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _
class CustomUser(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
backend.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q
UserModel = get_user_model()
class EmailBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserModel.objects.get(
Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
except MultipleObjectsReturned:
return User.objects.filter(email=username).order_by('id').first()
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
forms.py
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import get_user_model
from django import forms
from django.dispatch import receiver
from django.db.models.signals import pre_save
from .models import CustomUser
from django_email_verification import send_email
from django.views.generic.edit import FormView
class RegisterForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('email', 'username', 'password1', 'password2')
#receiver(pre_save, sender=CustomUser)
def set_new_user_inactive(sender, instance, **kwargs):
if instance._state.adding is True:
instance.is_active = False
else:
pass
class MyClassView(FormView):
def form_valid(self, form):
CustomUser = form.save()
returnVal = super(MyClassView, self).form_valid(form)
send_email(CustomUser)
return returnVal
class LoginForm(AuthenticationForm):
username = forms.CharField(label='Email / Username')
project url
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic import RedirectView
#new
from django_email_verification import urls as email_urls
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls')),
path('email/', include(email_urls)),
]+static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
settings.py
STATIC_URL = '/static/'
AUTH_USER_MODEL = 'accounts.CustomUser' # new
AUTHENTICATION_BACKENDS = ['accounts.backends.EmailBackend'] # new
LOGIN_REDIRECT_URL = '/'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
DEFAULT_FROM_EMAIL = ''
def verified_callback(CustomUser):
CustomUser.is_active = True
EMAIL_VERIFIED_CALLBACK = verified_callback
EMAIL_FROM_ADDRESS = 'noreply#aliasaddress.com'
EMAIL_MAIL_SUBJECT = 'Confirm your email'
EMAIL_MAIL_HTML = 'mail_body.html'
EMAIL_MAIL_PLAIN = 'mail_body.txt'
EMAIL_TOKEN_LIFE = 60 * 60
EMAIL_PAGE_TEMPLATE = 'confirm_template.html'
EMAIL_PAGE_DOMAIN = ''

Resources