When I try logging in with my custom user model I have been getting 'Please enter a correct email and password. Note that both fields may be case-sensitive.'. When I check the database I see the superuser has a password but my test user does not.
Things I've tried:
Checking database for users (They're present but no password)
Dropping database and running makemigrations
Superuser can login on both admin and regular login form just fine
accounts/models.py
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, company, phone, is_active=True, is_admin=False, is_staff=False, is_dealer=False, password=None):
if not email:
raise ValueError("Users must have an email address")
if not password:
raise ValueError("Users must have a password")
if not first_name:
raise ValueError("Users must have a first name")
if not last_name:
raise ValueError("Users must have a last name")
if not company:
raise ValueError("Users must have a company")
if not phone:
raise ValueError("Users must have a phone number")
user_obj = self.model(
email = self.normalize_email(email)
)
user_obj.set_password(password)
user_obj.first_name = first_name
user_obj.last_name = last_name
user_obj.company = company
user_obj.phone = phone
user_obj.admin = is_admin
user_obj.staff = is_staff
user_obj.dealer = is_dealer
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_superuser(self, email, first_name, last_name, company, phone, password=None):
user = self.create_user(
email,
first_name,
last_name,
company,
phone,
password=password,
is_admin=True,
is_staff=True
)
return user
def create_company_staff_user(self, email, first_name, last_name, company, phone, password=None):
user = self.create_user(
email,
first_name,
last_name,
company,
phone,
password=password,
is_staff=True
)
return user
def create_dealer_user(self, email, first_name, last_name, company, phone, password=None):
user = self.create_user(
email,
first_name,
last_name,
company,
phone,
password=password,
is_dealer=True
)
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
company = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True) # can login
online = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
staff = models.BooleanField(default=False)
dealer = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
# USERNAME_FIELD and password are required by default
REQUIRED_FIELDS = ['first_name', 'last_name', 'company', 'phone']
objects = UserManager()
def __str__(self):
return f"{self.first_name} {self.last_name}"
def get_full_name(self):
return f"{self.first_name} {self.last_name}"
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_admin(self):
return self.admin
#property
def is_staff(self):
return self.staff
#property
def is_dealer(self):
return self.dealer
#property
def is_active(self):
return self.active
#property
def is_online(self):
return self.online
accounts/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
# Register your models here.
User = get_user_model()
admin.site.register(User)
settings.py
AUTH_USER_MODEL = 'accounts.User'
main/templates/registration/login.html
<div class="container">
<div class="card my-4">
{% load static %}
<img class="img-fluid pb-4" src="{% static 'img/logos/logo-black.png' %}">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success"><i class="fas fa-sign-in-alt"></i> Login</button>
<input type="hidden" name="next" value="{{ next }}" />
</form>
</div>
</div>
myproject/urls.py
urlpatterns = [
path("", include('main.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I don't know what else to try. All I need is to be able to sign in with email rather than a username and have two types of users. (staff and dealer)
EDIT: I just checked my database and it appears there is not a password for my test user.
You should register your User model with the UserAdmin from the auth package. It should just plug into your model and will give you the custom forms that will create your users correctly
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
User = get_user_model()
admin.site.register(User, UserAdmin)
You can't just assign password=password like this. Instead try user.set_password(password)
Related
I have CRUD operations for users, which can be done only from the admin role. I have 6 different roles, that I made by creating groups and assign users to specific group from the admin panel.
My question is is there some way to include these group fields with drop down menu when admin create new user, so he can choose what group to assign the new user but not from the admin panel?
any help would be appreciated :)
model.py
class CustomUserManager(BaseUserManager):
def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
username = models.CharField(max_length=30, blank=True, default='')
is_superuser = models.BooleanField(default=True)
is_admin = models.BooleanField(default=True)
is_employee = models.BooleanField(default=True)
is_headofdepartment = models.BooleanField(default=True)
is_reception = models.BooleanField(default=True)
is_patient = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
forms.py
class UserForm(ModelForm):
class Meta:
model = CustomUser
fields = ['email', 'password',]
useradd.html
<h1 class="display-4">Add new user</h1>
<form action="" method="post" autocomplete="off">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Save </button>
views.py
#login_required
#admin_only
def users(request):
context = {'users': CustomUser.objects.all()}
return render(request, 'users.html', context)
#login_required
def users_add(request):
if request.method == "POST":
form = UserForm(request.POST)
if form.is_valid():
users = CustomUser.objects.create_user(**form.cleaned_data)
#login(request, users)
# redirect, or however you want to get to the main view
return redirect('feedback:users')
else:
form = UserForm()
return render(request, 'useradd.html', {'form': form})
You can use ModelChoiceField to include select widget in your form. So please try this code:
forms.py
from django.contrib.auth.models import Group
from django.forms import ModelForm, ModelChoiceField
from app.model import CustomUser
class UserForm(ModelForm):
class Meta:
model = CustomUser
fields = [
'email',
'password',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['group'] = ModelChoiceField(
queryset=Group.objects.all(),
empty_label='No group'
)
Change CustomUserManager.create_user method in model.py
from django.contrib.auth.models import Group
class CustomUserManager(BaseUserManager):
def create_user(self, email: str, password: str, group: Group, **extra_fields):
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
if group is not None:
group.user_set.add(user)
return user
When I create a user with my custom user model I cannot sign in. It just keeps telling me Please enter a correct email and password. Note that both fields may be case-sensitive. I thought I should check if I can see my test user in the db. I know only staff accounts can login to the admin but I'm using a different login form.
If I'm not mistaken it looks like there aren't any users in my database.
myproject=# \dt accounts_user
List of relations
Schema | Name | Type | Owner
--------+---------------+-------+------------------
public | accounts_user | table | myprojectuser
(1 row)
Here's my user model:
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
PermissionsMixin,
)
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, company, phone, is_active=True, is_admin=False, is_staff=False, is_dealer=False, password=None):
if not email:
raise ValueError("Users must have an email address")
if not password:
raise ValueError("Users must have a password")
if not first_name:
raise ValueError("Users must have a first name")
if not last_name:
raise ValueError("Users must have a last name")
if not company:
raise ValueError("Users must have a company")
if not phone:
raise ValueError("Users must have a phone number")
user_obj = self.model(
email = self.normalize_email(email)
)
user_obj.set_password(password)
user_obj.first_name = first_name
user_obj.last_name = last_name
user_obj.company = company
user_obj.phone = phone
user_obj.admin = is_admin
user_obj.staff = is_staff
user_obj.dealer = is_dealer
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_superuser(self, email, first_name, last_name, company, phone, password=None):
user = self.create_user(
email,
first_name,
last_name,
company,
phone,
password=password,
is_admin=True,
is_staff=True
)
return user
Perhaps there's something wrong in my admin.py?
from django.contrib import admin
from django.contrib.auth import get_user_model
# Register your models here.
User = get_user_model()
admin.site.register(User)
Hopefully someone can help me as I'm really stuck here.
I'm not 100% sure why your issue arises (considered you enterer it in the correct format), but this should give you a basic working solution to build upon:
forms.py
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
# Adjusting the default UserCreationForm
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', # etc.]
admin.py
from django.contrib import admin
from .models import User
admin.site.register(User)
models.py
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
# Inherit from AbstractBaseUser to extend User Model
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
company = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True) # can login
online = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
staff = models.BooleanField(default=False)
dealer = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
Also I am not sure which tutorial (this?) you followed, but personally I don't have models both in models.py and admin.py.
Login extension - views.py
# function for login logic
def loginPage(request):
if request.method == 'POST':
# get input values
username = request.POST.get('username')
password = request.POST.get('password')
# check if user has account in db
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('render_calculator')
context = {}
return render(request, 'login.html', context)
def registerPage(request):
# define the form, in this case Djangos default UserCreation
form = CreateUserForm()
# check if form inputs are valid after submitting, the save 'post' user
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
# Save User to db
form.save()
# get input values
username = request.POST.get('username')
password = request.POST.get('password')
email = request.POST.get('email')
return redirect('render_login')
context = {'form': form}
return render(request, 'register.html', context)
login.html
<form method="post" action="">
{% csrf_token %}
<div class="formFieldLoginContainer">
<input type="text" name="username" placeholder="username">
<input type="password" name="password" placeholder="password">
</div>
<input type="submit" id="loginSubmitButton" name="Login User" value="Login">
<div id="noAccountDiv"> Don't have an account yet?
Sign Up
</div>
</form>
register.html
<form method="post" action="">
{% csrf_token %}
<!-- loop form object and create div for each form field included -->
{% for field in form %}
<div class="formFieldContainer">
<div class="registerLabel">{{field.label}}</div>
<div class="registerField">{{field}}</div>
</div>
{% endfor %}
<!-- render possible input form errors -->
{{form.errors}}
<input type="submit" id="submitButton" name="Create User" value="Register">
<div id="alreadyAccountDiv"> Already have an account?
Login
</div>
</form>
ulrs.py
urlpatterns = [
path('login/', views.loginPage, name='render_login'),
path('logout/', views.logout_view),
path('email/', include(mail_urls)),
path('password/', views.change_password, name='change_password'),
]
I have created a custom user model and using that model I have created sign up form. but whenever I click submit button ,form does not validate and don't store data in database. It just redirects me to home without storing data in database. but I can store data manually in database.
models.py
from django.db import models
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class SignUpManager(BaseUserManager):
def create_user(self, email,age,name, username, password=None):
if not email:
raise ValueError("insert user")
if not username:
raise ValueError("insert username")
if not name:
raise ValueError("insert name")
if not age:
raise ValueError("insert age")
user = self.model(
email=self.normalize_email(email),
username=username,
age=age,
name=name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email,name,age,username, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
age=age,
name=name,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserSignupModel(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
age = models.CharField(max_length=15)
name = models.CharField(max_length=15)
username = models.CharField(max_length=15, unique=True)
date_joined = models.DateTimeField(verbose_name="date joined", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="last login", auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['email','name','age']
objects = SignUpManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
#migrate --run-syncdb in case no work
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from diabetes.models import UserSignupModel
class UserSignupForm(UserCreationForm):
email=forms.EmailField(max_length=60,help_text="add a valid email address")
name=forms.CharField(max_length=15,help_text="add a valid name")
age=forms.CharField(max_length=15)
class Meta:
model=UserSignupModel
fields=('email','name',"username",'age',"password1","password2")
views.py
from django.shortcuts import render,redirect
from django.contrib.auth import login,authenticate
from diabetes.forms import UserSignupForm
# Create your views here.
def home(request):
return render(request,'diabetes/home.html')
def signupuser(request):
if request.method == 'POST':
form=UserSignupForm(request.POST)
if form.is_valid():
form.save()
email=form.cleaned_data.get('email')
raw_password=form.cleaned_data.get('password1')
account=authenticate(email=email,password=raw_password)
login(request,account)
return redirect('home')
else:
return redirect('home')
else:
form = UserSignupForm()
return render (request,'diabetes/signupuser.html',{'form':form})
signupuser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST">
{% csrf_token %}
{{ form.as_p}}
<input type="submit">SUBMIT</input>
</form>
</body>
</html>
You have got error in the signup method in views.py. Refer to this code and see what changes can be made.
# method for registration page
def register_view(request):
register_form = AddUserForm(request.POST or None)
# if the data provided in the form is valid than save the form
if register_form.is_valid():
user = register_form.save(commit=False)
user = register_form.save()
raw_password = register_form.cleaned_data.get('password1')
user = authenticate(request, email=user.email, password=raw_password)
group = Group.objects.get(name='Student')
user.groups.add(group)
if user is not None:
login(request, user)
return redirect('login')
return render(request, 'apps/register.html', {'register_form': register_form})
I'm totally new to Django. I've read over the docs, and I've looked up things on here, but there's not much. I'm basically trying to having profiles display on a page that I've already created. I'm using a custom user model.
And the thing is, I was suggested to simply take out 'user' in 'user=request.user, but problem is if I do that, than I get 'Profile' is not iterable.
Error at line description = Profile.objects.get(user=request.user).description:
FieldError at /mingle/
Cannot resolve keyword 'user' into field. Choices are: date_joined, description, email, given_vote, id, is_active, is_admin, is_staff, is_superuser, last_login, logentry, matches, password, photo, username, uservote
Request Method: GET
Request URL: http://localhost:8000/mingle/
Django Version: 2.2.3
Exception Type: FieldError
Exception Value:
Cannot resolve keyword 'user' into field. Choices are: date_joined, description, email, given_vote, id, is_active, is_admin, is_staff, is_superuser, last_login, logentry, matches, password, photo, username, uservote
Exception Location: /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/sql/query.py in names_to_path, line 1420
Python Executable: /Library/Frameworks/Python.framework/Versions/3.7/bin/python3
Python Version: 3.7.3
Python Path:
['/Users/papichulo/Documents/DatingAppCustom',
'/Library/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
'/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
'/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
'/Users/papichulo/Library/Python/3.7/lib/python/site-packages',
'/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages']
Server time: Sun, 5 Apr 2020 19:20:01 +0000
mingle.html
{% extends "dating_app/base.html" %}
{% load bootstrap4 %}
{% block content %}
<div class="container">
{% if user %}
<div class="container content is-child box column is-4 is-offset-4">
<img src="{{ profile.photo.url }}">
<p style="font-size: 25px">{{profile}}</p>
<b>Bio:</b>
<p>{{profile.description}}</p>
</div>
{% else %}
<p>Wait for more people to join!</p>
<p>Help us get more user. Share this link to your friends! http://localhost:8000/</p>
{% endif %}
{% endblock %}
views.py
def mingle(request):
try:
user = (Profile.objects.exclude(id=request.user.id).exclude(uservote__voter=request.user).order_by('?')[0])
except IndexError:
user = None
print(Profile.username)
try:
description = Profile.objects.get(user=request.user).description
except Profile.DoesNotExist:
create = Profile.objects.get_or_create(user = request.user)
return redirect('profile')
match = models.Profile.objects.get(user=request.user).matches.all()
context = dict(user = user, match = match)
return render(request, 'dating_app/mingle.html', context)
models.py
class ProfileManager(BaseUserManager):
def create_user(self, username, email,description,photo, password=None):
if not email:
raise ValueError("You must creat an email")
if not username:
raise ValueError("You must create a username!")
if not description:
raise ValueError("You must write a description")
if not photo:
raise ValueError("You must upload a photo")
user = self.model(
email=self.normalize_email(email),
username = username,
description= description,
photo= photo,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email,description,photo, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
description=description,
photo=photo,
)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class Profile(AbstractBaseUser):
class Meta:
swappable = 'AUTH_USER_MODEL'
email = models.EmailField(verbose_name="email")
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
#what I added
description = models.TextField()
photo = models.ImageField(upload_to='profile_photo',blank=False, height_field=None, width_field=None, max_length=100)
matches = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='+', blank=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['description','photo','email']
objects = ProfileManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self,app_label):
return True
class UserVote(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
voter = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='given_vote', on_delete=models.CASCADE)
vote = models.BooleanField(default=False)
class Meta:
unique_together = (('user', 'voter'))
Did you set AUTH_USER_MODEL in your settings.py to point to your custom Profile model? If so, request.user will already be the user that you're trying to filter for.
You can change:
description = Profile.objects.get(user=request.user).description
To:
description = request.user.description
I have a custom user model subclassing AbstractBaseUser:
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=254)
username = models.CharField(max_length=254, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['name']
objects = UserManager()
def __str__(self):
return self.email
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
after migrating, I created a simple form for sign up which I am mapping two fields from the model: email and name like below:
class SignUpForm(ModelForm):
class Meta:
model = CustomUser
fields = ['name', 'email']
I then have the view to render a template to show the above fields as input fields:
class MyRegisterView(RegisterView):
def get(self, request):
form = SignUpForm()
return render(request, "registration.html", context={"form": form})
and in the template, I am simply doing:
<form method="post">
{% csrf_token %}
<h3>Sign Up</h3>
<div>
<label for="name">
<input id = "name" name = "name" class="textfield" type="text" value="" placeholder="Name">
</label>
</div>
<div>
<label for="email">
<input id = "email" name = "email" class="textfield" type="email" value="" placeholder="Email">
</label>
(also including passwords and so on)
The problem is that when I add the name field and then submit, the name field in the database is not getting populated (the email is and the user account is created... but without the name). Why is that?
below is my custom BaseUserManager that I am subclassing: ( could it be that I am missing something in the below Usermanager?)
class UserManager(BaseUserManager):
def _create_user(self, name, email, password, is_staff, is_superuser, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
now = timezone.now()
email = self.normalize_email(email)
user = self.model(
name=name,
email=email,
is_staff=is_staff,
is_active=True,
is_superuser=is_superuser,
last_login=now,
date_joined=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, name, email, password, **extra_fields):
return self._create_user(name, email, password, False, False, **extra_fields)
def create_superuser(self, name, email, password, **extra_fields):
user = self._create_user(name, email, password, True, True, **extra_fields)
user.save(using=self._db)
return user