I'm trying to make an authentication system using Django using only 3 fields for SignUp (username & email & password ) and 2 fields for sign in ( username & password )
I think that the error that I get has relation to database, which I haven't used my models file yet, I don't know where the problem is coming from, is it from the signup function or the signing function
IntegrityError at /signup
UNIQUE constraint failed: auth_user.username
Request Method: POST
Request URL: http://127.0.0.1:8000/signup
Django Version: 3.2.6
Exception Type: IntegrityError
Exception Value:
UNIQUE constraint failed: auth_user.username
Exception Location: C:\Users\dell\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py, line 423, in execute
Python Executable: C:\Users\dell\AppData\Local\Programs\Python\Python39\python.exe
Python Version: 3.9.0
Python Path:
['C:\\Users\\dell\\Desktop\\greenaftech',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\python39.zip',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\DLLs',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\lib',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages\\win32',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages\\win32\\lib',
'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages\\Pythonwin']
Server time: Sat, 30 Apr 2022 00:24:12 +0000
this is my views.py:
from django.shortcuts import render,redirect
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib import messages
# Create your views here.
def home(request):
return render(request,"website/index.html")
def signup(request):
if request.method=="POST":
username=request.POST.get('username')
password=request.POST.get('password')
email=request.POST.get('email')
myuser= User.objects.create_user(username,email,password)
myuser.save()
messages.success(request,"Your Account has been created.")
return redirect('signin')
return render(request,"website/signup.html")
def signin(request):
if request.method=='POST':
usern=request.POST.get('username')
passs=request.POST.get('password')
user=authenticate(username=usern,password=passs)
if user is not None:
login(request,user)
userr=user.username
return render(request,"website/index.html",{'username':userr})
else:
messages.error(request,"Wrong Infos")
return redirect('home')
return render(request,"website/signin.html")
def signout(request):
pass
and these are my URLs.py :
from django.contrib import admin
from django.urls import path,include
from . import views
urlpatterns = [
path('',views.home,name='home'),
path('signup',views.signup,name='signup'),
path('signin',views.signin,name='signin'),
path('signout',views.signout,name='signout'),
]
That error would be incurred if you try and create two users with the same username, with your uath_user model's username field having a unique=True constraint (which prevents two records having the same value in that field).
Note that if you use User.objects.create(...) as opposed to User(username="username"...) it will automatically save the new record, so myUser.save() may be trying to replicate that creation, creating the constraint issue, while still allowing you to see the item in admin
Related
When I click on sign in button I get integrity error!! I have checked in my admin site and all users are properly visible which I had signed up. But when I click sign in button with entries already registered in admin, my code crashes and gives integrity error!!
views.py:
from django.http import HttpResponse
from django.shortcuts import redirect, render , HttpResponse
from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth import authenticate , login
# Create your views here.
def home(request):
return render(request,"authentication/index.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')
pass1=request.POST.get('pass1')
pass2=request.POST.get('pass2')
myuser=User.objects.create_user(username,email,pass1) #creating user
myuser.first_name=fname
myuser.last_name=lname
myuser.save()
messages.success(request,"Your account has been successfuly created")
return redirect('/signin')
return render(request,"authentication/signup.html")
def signin(request):
if request.method=='POST':
username=request.POST.get('username')
pass1=request.POST.get('pass1')
user=authenticate(username=username,password=pass1)
if user is not None:
login(request,user)
return render(request,"authentication/index.html")
else:
messages.error(request,"Bad credentials")
redirect('home')
return render(request,"authentication/signin.html")
def signout(request):
pass
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Tutorial
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.models import User
def register (request):
form = UserCreationForm(request.POST)
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages():
print(form.error_messages[msg])
return render(request,
'main/register.html',
context={'form':form})
but still I get this error " 'dict' object is not callable
Request Method: POST Request
URL: http://127.0.0.1:8000/register/ Django Version: 3.0.7
Exception Type: TypeError
Exception Value: 'dict' object is not callable "
for msg in form.error_messages():
print(form.error_messages[msg])
First, no where in the Django documentation is using form.error_messages for the error messages, and if form.error_messages is a dict, then there is a python problem -> dict is not callable, get the list of keys by calling .keys() on your dict.
According to Newest Django's doc to get errors from your forms is using form.errors.
for field, msg in form.errors.items():
print(f'Field {key}: {msg}')
I understand that in order to override from django.contrib.auth.views.LoginView one has to use a subclass Class(LoginView) in views.py.
However, in my views.py I only have views declared with def my_view(request)
In old versions of Django I could just do
from django.contrib.auth.views import login, logout
def login_user(request):
result = login(request=request, template_name='Market/pages/login.html')
return result
What's the modern Django equivalent of this? The documentation has this example, that forces me rewrite the whole username/password logic into my view:
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
# Redirect to a success page.
...
else:
# Return an 'invalid login' error message.
...
How can I use a view function (not class!) and still have the automatic managing of the submitted request?
You're missing the point. The reason behind the move to class-based views is that they are more configurable than function-based ones.
In this case, you don't even need to define your own view to get the result you want; you can just do it in the URL:
path('login/', views.LoginView.as_view(template_name='Market/pages/login.html'), name='login')
Problem
The django.contrib.auth.login function is succeeding, but the session does not seem to persist.
Code
I am creating my own set of functions to use with an AJAX client inside of my Django server.
I have the following code in urls.py:
from django.contrib.auth import authenticate, login
from django.conf.urls import url
from django.http import JsonResponse
import json
def auth_login(request):
username = json.loads(request.body)['username']
password = json.loads(request.body)['password']
user = authenticate(request, username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return JsonResponse({}, status=200)
else:
return JsonResponse({}, status=400)
urlpatterns = [
url(r'auth/login/', auth_login, name='login')
]
Details
As mentioned above, the call to login() succeeds. request.session is being set properly, and I can access if from within auth_login. On subsequent requests, request.session does not exist and django.contrib.auth.get_user returns AnonymousUser.
(Possibly relevant) I am also using the seemingly-popular https://django-tenant-schemas.readthedocs.io/en/latest/. This urls.py file is in an application that is per-tenant, so the user is actually authenticating on tenantname.hostname.com/tenant/auth/login/.
The tenant's django_session table is being set correctly. For each attempted login, I can see session_key, session_data, and expire_data.
The cookie for tenantname.hostname.com is empty after attempted logins.
I'm just out of ideas as to what other things I could try to lead me to a solution.
Question(s)
Any thoughts as to why this session isn't actually saved into the cookie?
OR
Thoughts as to what else I could try that could lead me to a solution?
I am working on a django project and I am using the default auth app for authentication.
I know that there is a last_login field in user model which stores the user's last login time.
When a staff user logs in first time into the admin panel, I want to check if last_login field is none & redirect him to the change password page.
Where should I put this check?
What I have tried so far:
I have tried to use a custom login form and override the default confirm_login_allowed method on it, but it seems like I can only raise a validation error to block login attempt using these.
I also tried using django.contrib.auth.signals.user_logged_in Signal but that also does not allow me to return a redirect response when last_login is None.
I want to know how I can return a redirect response after the user has been authenticated.
Customise Django admin using AdminSite and use login_form attribute to give the custom login form for the Admin login page.
admin.py
class MyAdminSite(AdminSite):
login_form = CustomAdminLoginForm
admin_site = MyAdminSite(name='myadmin')
admin_site.register(User)
admin_site.register(Group
urls.py
When overriding the Admin we have to get rid of Django default admin
from app.admin import admin_site
url(r'^admin/', admin_site.urls)
forms.py
AuthenticationForm have the confirm_login_allowed method use this to grant permission to login in or not login in.
class CustomAdminLoginForm(AuthenticationForm):
def confirm_login_allowed(self, user):
if user.last_login:
raise ValidationError(mark_safe('Hey first time user please reset your password here... test'), code='inactive')
Note: There is lot of edge cases you have to consider for this approach.
What if user not set the password in the first time and how you're going to handle second attempt..? This time last_long not None. Although date_joined comes rescue. last_login == date_joined
But What if the user not set the password in first day and comes next day ?
Edit:
You can use signal to check the logged in user and apply the config_login_allowed logic here...?
from django.contrib.auth.signals import user_logged_in
def change_password_first_time(sender, user, request, **kwargs):
# Your business logic here...
user_logged_in.connect(change_password_first_time)
Django admin is not that configurable. You should hook into its internal views. Login/logout views are inside Django AdminSite class (the one you usually access by admin.site). My implementation is a bit hacky but small:
Paste at the top of urls.py
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class MyAdminSite(AdminSite):
def login(self, request, extra_context=None):
new_user = False
user = None
username = request.POST.get('username') # Hack to find user before its last_login set to now.
if username:
user = User.objects.filter(username=username).first()
if user:
new_user = user.last_login is None
r = super(MyAdminSite, self).login(request, extra_context)
if new_user and request.user == user and isinstance(r, HttpResponseRedirect): # Successful logins will result in a redirect.
return HttpResponseRedirect(reverse('admin:password_change'))
return r
admin.site = MyAdminSite()
If you want a cleaner solution I suggest to use a boolean inside user model instead of relying on last_login so you could just check request.user instead of my hack into request.POST.
You could read AdminSite.login and django.contrib.auth.views.login to see what is actually happening inside Django.
It was a big problem for me at once. I found a way to do it easy. Create a different variable to save the value of the users logged in data, when user is trying to login.
Below is my code:
if user.last_login is None:
auth.login(request,user)
return redirect(alertPassword)
# when user is login for the first time it will pass a value
else:
auth.login(request,user)
return redirect(moveToLogin)
def moveToLogin(request):
return render(request,"home.html")
def alertPassword(request):
first_login=True
return render(request,"home.html",{"first_login":first_login})
#it will pass a value to the template called first login is True
Then go to your template and add this:
{% if first_login==True%}
# Put anything you want to be done
# In my case I wanted to open a new window by using script.
<script>
window.open("popUpWindow")
</script>
{%endif%}