Users not writing to database (Postgresql) - django

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'),
]

Related

How to register user using your own Model Django

I am having trouble registering a user as a PetOwner. I'm not sure what I am suppose to code in my signup view. I can signup a user and that user does not have admin or staff status which is great because they should not have these privileges. Problem is that I do not just want them to be a user but I want them to be a PetOwner. Currently, they are only a User not a PetOwner. What am I doing wrong here or what do I have to add.
in models.py
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class PetOwner(models.Model):
"""Model representing a pet owner."""
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50, help_text="Enter owner's first name")
last_name = models.CharField(max_length=50, help_text="Enter owner's last name")
email = models.EmailField(
max_length=50, blank=True, unique=True, help_text="Enter owner's email"
)
phone_number = models.CharField(
max_length=15, blank=True, unique=True, help_text="Enter owner's phone number"
)
address = models.ForeignKey(
"Address", on_delete=models.SET_NULL, null=True, blank=True
)
class Meta:
"""Controls default ordering of records when querying the Model type."""
ordering = ["first_name", "last_name"]
def __str__(self):
"""String for representing the Model object."""
return self.first_name
def get_absolute_url(self):
"""Returns the url to access a detail record of this pet owner."""
return reverse("petowner_detail", args=[str(self.id)])
in views.py
from django.shortcuts import render, redirect
from django.views import generic
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import PetOwner, Pet, Breed, Address
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password1")
user = authenticate(username=username, password=password)
login(request, user)
return redirect("/")
else:
return render(request, "signup.html", {"form": form})
else:
form = UserCreationForm()
return render(request, "signup.html", {"form": form})
in urls.py
path("signup/", views.signup, name="signup"),
in signup.html
{% extends 'base.html' %}
<h1>Sign Up Page</h1>
{% block content %}
<form method="post">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Register</button>
</form>
{% endblock content %}
You need save the related PetOwner after the user.
if form.is_valid():
user = form.save()
# Create the related data here...
petOwner = PetOwner(
user=user,
first_name=user.first_name,
last_name=user.last_name
)
petOwner.save()
login(request, user)
return redirect("/")
you should use Foreign key instate of one to one field to pet owner and give them roll as pet owner example is below
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
roll={petowner, roll1, roll2}
user = models.OneToOneField(User, on_delete=models.CASCADE, add roll here)
in views.py just check roll and create pet owner object in pet owner model
also you can do this without roll just write logic for if user created then when user will be added it should create a pet owner object automatically
for example
if user:
classrooms = Classroom.objects.filter(id=id, is_active=True)
if users.exists():
user = users.first()
is_user = (user.user==request.user)
if not pet_owner:
pet_owner.objects.create(user=user, user=request.user).save()
this is just an example names and model can be changed

How to assign users in groups from Django views?

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

Custom user no password in db

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)

How to retrieve data from extended user model

I am trying to make a simple signup/login page through django.
I have used UserCreationForm and used a model UserProfile to extend the user model.
I want to retrieve the data posted from form i.e department at my home page after user logged in.
I am new to django so brief explanation would be appreciated.
Thanks in advance
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from mysite.core.models import UserProfile
from django.db import models
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
department = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email','password1', 'password2', 'department',)
def save(self, commit=True):
# Save the provided password in hashed format
user = super(SignUpForm, self).save(commit=False)
user_profile = UserProfile(user=user, department=self.cleaned_data['department'])
user.save()
user_profile.save()
return user, user_profile
views.py
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from mysite.core.forms import SignUpForm
#login_required
def home(request):
return render(request, 'home.html')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user,user_profile = form.save(commit=False)
username = user.cleaned_data.get('username')
raw_password = user.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,unique=True)
department = models.CharField(max_length=500, blank=True)
home.html in templates:
{% extends 'base.html' %}
{% block content %}
<h2>Welcome, <small>{{ user.username }}</small>!</h2>
<p>Your email address: {{ user.email }}</p>
<p>Department: {{ user_profile.department }}</p>
{% endblock %}
I am able to print username and email but department is coming empty.
Firstly, you have the wrong relationship. There is a one-to-one relationship between User and UserProfile; a user can only have one profile, and a profile can only belong to one user. The way you have it now, a user can have many profiles, which doesn't make sense.
You should replace the ForeignKey with a OneToOneField.
Once you have done that, you will be able to access the profile data via the relationship: user.userprofile.department, and so on.

Extending User Profile

Please i need help .I have a problem in extending userprofile.At first everything seems to be working good until now .Please i need help in resolving this bellow is my code .
Model.py
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,related_name="userprofile")
date =models.DateField(blank=False,null= True)
bio = models.TextField(max_length=500,blank=False)
picture = models.ImageField(upload_to="profile_image",null=True,blank=True)
company = models.CharField(max_length=500,null=True)
def __str__(self):
return self.user.username
#receiver(post_save,sender=User)
def create_profile(sender,instance,created,**kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save,sender=User)
def save_user_profile(sender,instance,**kwargs):
instance.UserProfile.save()
views.py
def update_profile(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST,request.FILES,instance=request.user.userprofile)
if profile_form.is_valid():
profile_form.save()
messages.success(request,'Your Profile has been Updated')
return redirect('success:profile_account')
else:
messages.error(request,'fill out the fields correctly')
else:
profile_form = ProfileForm(instance=request.user.userprofile)
return render(request,"success/user_account/edit_profile.html",{'profile_form':profile_form})
html.form
<form action='{{ action_url }}' method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ profile_form.bio}}{{profile_form.bio.error}}
{{ profile_form.picture}}{{profile_form.picture.error}}
<div class="pc"><label>Company Name:</label>{{ profile_form.company}}{{profile_form.company.error}}
{{ profile_form.date}}{{profile_form.date.error}}
<button type="submit">Save changes</button>
Error I get
Forbidden (403)
CSRF verification failed. Request aborted. Help
Reason given for failure:
CSRF token missing or incorrect.
In general, this can occur when there is a genuine Cross Site Request
Forgery, or when Django's CSRF mechanism has not been used correctly.
For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function passes a request to the template's render method.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as
well as those that accept the POST data.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to
reload the page with the form, because the token is rotated after a
login.
You're seeing the help section of this page because you have DEBUG =
True in your Django settings file. Change that to False, and only the
initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
this is the best way to extend user model profile
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.contrib.auth.models import BaseUserManager
class AccountManager(BaseUserManager):
def create_user(self, username, password=None, **kwargs):
if not username:
raise ValueError('Users must have a valid email username.')
if not kwargs.get('email'):
raise ValueError('Users must have a valid email.')
email = kwargs.get('email')
account = self.model(
username=username, email=self.normalize_email(email)
)
account.set_password(password)
account.save()
return account
def create_superuser(self, username, password, **kwargs):
account = self.create_user(username, password, **kwargs)
account.is_admin = True
account.save()
return account
class Account(AbstractBaseUser):
username = models.CharField(max_length=40, unique=True)
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
def __unicode__(self):
return self.email
def get_full_name(self):
return ' '.join([self.first_name, self.last_name])
def get_short_name(self):
return self.first_name
modify this example and then in forms.py just import you model user profile