I have been working on a project where admin registers users to use the website. say in my case admin registers teachers and students of the school. I need some way to create random password for every new user and a email will be sent using registered email with the password. I am using custom user model.
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Users must have email Id")
if not username:
raise ValueError("Users must have an username")
user = self.model(email=self.normalize_email(email),
username=username)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password=None):
user = self.create_user(email=self.normalize_email(email),
username=username,
password=password)
user.role = 'ADM'
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractUser):
email = models.EmailField(verbose_name="Email", unique=True)
ROLE_CHOICES = [
('STD', 'STUDENT'),
('THR', 'TEACHER'),
('ADM', 'ADMIN')
]
role = models.CharField(max_length=3, choices=ROLE_CHOICES, default='STD')
username = models.CharField(max_length=50, unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
date_of_birth = models.DateField(null=True)
description = models.TextField(null=True)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
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_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
objects = MyAccountManager()
here my register view.
#login_required
def register(request):
if not request.user.is_superuser:
return HttpResponse('Unauthorized', status=401)
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
email = form.cleaned_data.get('email')
password = User.objects.make_random_password(length=10,
allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
form.save()
user = User.objects.filter(username=username)
user.set_password(password)
user.save()
send_mail(
'Login details',
'Here is your login details \n username : ' + username + '\n password : ' + password,
from_email=None,
recipient_list=[email],
fail_silently=False,
)
messages.success(message="Email has been sent to " + email + ".")
return redirect('register')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
here is my UserRegisterForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
def __init__(self, *args, **kwargs):
super(UserCreationForm, self).__init__(*args, **kwargs)
del self.fields['password1']
del self.fields['password2']
class Meta:
model = User
fields = ['username', 'email', 'role']
What are the possible ways I can set this. I tried by overriding form.save() by didnt seem to work.
Form .save() accepts an optional commit keyword argument, if you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database. You can modify the data and then save it.
def register(request):
...
f = UserRegisterForm(request.POST)
if f.is_valid():
u = f.save(commit=False)
raw_password = User.objects.make_random_password(...)
u.set_password(raw_password)
u.save()
...
Template
<form action="..." method="post">
{% csrf_token %}
{{ form }}
<input type="password" name="password1" value="random_value" hidden>
<input type="password" name="password2" value="random_value" hidden>
<input type="submit" value="Submit">
</form>
Related
Tysm in advance, for helping
Already a superuser is made but admin login or login view is not working, Some problem in authenticate it every time returns none if correct password and email are passed
Custom User Model
class UserManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Email Requierd!")
if not username:
raise ValueError("Username required!")
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
userid = models.UUIDField(
default=uuid.uuid4, editable=False, primary_key=True)
username = models.CharField(max_length=255, unique=True)
email = models.EmailField(max_length=255, unique=True)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now_add=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
#
USERNAME_FIELD = 'email'
#
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perm(self, app_label):
return True
Already a superuser is made but admin login or login view is not working, Some problem in authenticate it every time returns none if password and email are passed!
psql view
login view
def login_view(request):
user = request.user
if user.is_authenticated:
return redirect('home')
if request.POST:
form = LoginForm(request.POST)
if form.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
form = LoginForm()
return render(request, 'login.html', {'form': form})
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model, authenticate
User = get_user_model()
class UserCreateForm(UserCreationForm):
email = forms.EmailField()
#is_seller = forms.BooleanField
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class LoginForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(label='Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email', 'password']
def clean(self):
email = self.cleaned_data['email']
password = self.cleaned_data['password']
if not authenticate(request, email=email, password=password):
raise forms.ValidationError("Invlaid Login")
After login, it doesn't give me any errors and neither redirects to homepage!
After login, it doesn't give me any errors and neither redirects to homepage!
Tysm in advance, for helping
Try to set is_active field as default=True
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
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
I don't know why my form after submitting it always returns that the phone is required, i am stuck with this problem about one hour :(, i've seen lots of articles and questions that has been asked but without avail .
views.py:
def register(request):
if request.method == 'POST':
form = SignUpForm(request.POST or None)
if form.is_valid():
user = form.save(commit=False)
telephone = number_prettify(form.cleaned_data.get('telephone'))
user.phone = telephone
raw_password = form.cleaned_data.get('password1')
user.save()
user = authenticate(phone=user.phone, password=raw_password)
auth_login(request, user)
return redirect('/')
else:
form = SignUpForm()
return render(request, 'register.html', {'form': form})
here is my forms.py:
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
# from .models import Client
User = get_user_model()
class SignUpForm(UserCreationForm):
telephone = forms.CharField(label='Номер телефона', help_text='Required. Inform a valid phone number.',
widget=forms.TextInput(attrs={'placeholder': '___-__-__-__','class':"uk-input phone_us"}))
password1 = forms.CharField(label='Пароль',widget=forms.PasswordInput())
password2 = forms.CharField(label='Повторите пароль',widget=forms.PasswordInput())
agree_1 = forms.BooleanField()
agree_2 = forms.BooleanField()
def clean(self):
if not self.cleaned_data['agree_1']:
raise forms.ValidateError('You have to agree to out privacy')
class Meta:
model = User
fields = ('phone',)
here is also the models.py:
class Client(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(null=True, blank=True, unique=True)
phone = models.CharField(max_length=18,unique=True)
joined = models.DateTimeField(auto_now_add=True)
password = models.CharField(default='', null=False, max_length=255)
USERNAME_FIELD = 'phone'
class Meta:
db_table = 'client'
unique_together = ('phone',)
my register.html template:
<div class="uk-margin">
<label>
<div class="uk-margin-small-bottom">{{form.telephone.label}} <span>*</span></div>
{{form.telephone}}
</label>
</div>
<div class="uk-margin">
<label>
<div class="uk-margin-small-bottom">{{form.password1.label}} <span>*</span></div>
{{form.password1|add_class:"uk-input"}}
</label>
</div>
You should change the field from telephone to phone.
class SignUpForm(UserCreationForm):
phone = forms.CharField(label='Номер телефона', help_text='Required. Inform a valid phone number.',
widget=forms.TextInput(attrs={'placeholder': '___-__-__-__','class':"uk-input phone_us"}))
password1 = forms.CharField(label='Пароль',widget=forms.PasswordInput())
password2 = forms.CharField(label='Повторите пароль',widget=forms.PasswordInput())
agree_1 = forms.BooleanField()
agree_2 = forms.BooleanField()
def clean(self):
if not self.cleaned_data['agree_1']:
raise forms.ValidateError('You have to agree to out privacy')
class Meta:
model = User
fields = ('phone',)
I have written a custom form for the creation of a user.
The login works for the users created on the terminal with "python manage.py createsuperuser", but it doesn't work for the users created on the website. I have checked, and the creation form works; I mean, the user is created.
This is the form
class CustomUserCreationForm(UserCreationForm):
"""
A form that creates a user, with no privileges, from the given email and password.
"""
def __init__(self, *args, **kwargs):
super(CustomUserCreationForm, self).__init__(*args, **kwargs)
class Meta:
model = CustomUser
fields = ("email",)
The model
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=254, unique=True, null=True)
first_name = models.CharField(max_length=254, blank=True)
second_name = models.CharField(max_length=254, blank=True)
email = models.EmailField(blank=True, unique=True)
address1 = models.CharField(max_length=254, blank=True)
address2 = models.CharField(max_length=254, blank=True)
area_code = models.CharField(max_length=20, blank=True)
country_code = models.CharField(max_length=10, blank=True)
date_joined = models.DateTimeField(_('date joined'), default=datetime.now())
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'address1', 'address2', 'area_code', 'country_code']
objects = CustomUserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_absolute_url(self):
return "/users/%s" % urlquote(self.email)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
return full_name.strip()
def get_short_name(self):
"""
Returns the first name for the user.
"""
return self.first_name
def email_user(self, subject, message, from_email=None):
"""
Sends an email to this user.
"""
send_email(subject, message, from_email, [self.email])
The register view
def register(request):
registered = False
if request.method == 'POST':
user_form = CustomUserCreationForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
else:
print user_form.errors
else:
user_form = CustomUserCreationForm()
return render(request, 'register.html', {'user_form': user_form, 'registered': registered})
The login view
def login(request):
if request.method == 'POST':
login_form = CustomUserLoginForm(data=request.POST)
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username, password=password)
if user:
if user.is_active:
auth.login(request, user)
return HttpResponseRedirect('/')
else:
return HttpResponse("Your account is disabled.")
else:
print "Invalid login details: {0}, {1}".format(username, password)
return HttpResponse("Invalid login details supplied. Get back to the homepage.")
else:
login_form = CustomUserLoginForm()
return render(request, 'login.html', {'login_form': login_form})
What am I missing here?
Thanks!
First fix the class:
class CustomUser(AbstractUser, PermissionsMixin):
AbstractUser is a real User Model, the BaseUser is just the meta class.
To create a new user you should use this line, in the form or in the register view:
User.objects.create_user(username=username,email=email,password=password)
Note that set_password is used to change the password, and it logs out this user after the password changes.
For almost three days I was trying to overcome same issue. I even wrote AUTHENTICATION_BACKEND. Only after that, a message was displayed on the form that the user is not active. When in save method I assigned True to user.is_active
def save(self):
user = super().save(commit=False)
user.is_active = True
user.save()
This worked for me. I hope it will work for you as well. (Note: I was not aware of rules and posted same message for similar questions to help others as well, when get notice not to do it. If anyone will see my answer for other questions please ignore it. The above answer is edited one and mostly related to this exact issue)