I modified the user model as shown below, to make users log in via phone.
from django.db import models
import datetime
from django.core.mail import send_mail
from django.contrib.auth.models import (
AbstractBaseUser, BaseUserManager
)
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.core.validators import RegexValidator
class UserManager(BaseUserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
def create_user(self,phone_number,password=None,is_staff=False,is_active = True, is_admin = False, is_vendor = False):
if not phone_number:
raise ValueError("Users Must Have a phone number")
if not password:
raise ValueError("Users must have a password")
user = self.model(
phone_number )
user.set_password(password)
user.is_staff = is_staff
user.is_active = is_active
user.is_admin = is_admin
user.is_vendor = is_vendor
user.save(using=self._db)
return user
def create_staffuser(self,phone_number, password=None):
user = self.create_user(
phone_number,
password=password,
is_staff=True
)
return user
def create_superuser(self,phone_number, password=None):
user = self.create_user(
phone_number,
password=password,
is_admin=True,
is_staff=True
)
return user
def create_vendoruser(self,phone_number, password=None):
user = self.create_user(
phone_number,
password=password,
is_vendor=True
)
return user
class User(AbstractBaseUser):
phone_number = models.CharField(max_length=20, unique=True)
date_joined = models.DateField(auto_now_add = True)
is_active = models.BooleanField(default = True)
is_staff = models.BooleanField(default = False)
is_admin = models.BooleanField(default = False)
is_vendor = models.BooleanField(default = False)
is_basic = models.BooleanField(default = False)
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
return self.phone_number
# def save(self, *args, **kwargs):
# self.email = self.email.lower()
# return super(User, self).save(*args, **kwargs)
def get_full_name(self):
return self.phone_number
def get_short_name(self):
return self.phone_number
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def get_type(self):
if self.vendor:
return self.vendor_user
else:
return self.basic_user
#property
def staff(self):
return self.is_staff
#property
def admin(self):
return self.is_admin
#property
def active(self):
return self.is_active
#property
def vendor(self):
return self.is_vendor
#property
def basic(self):
return self.is_basic
USERNAME_FIELD = 'phone_number'
Then I created a superuser and tried to log in, but couldn't.
Upon checking the database from the python shell, I realized that the database had an empty phone number field for the superuser I created.
So the problem is: phone number is not properly saving when I create superuser
In your code you write:
user = self.model(phone_number)
(reformatted)
But if you create a model instance, all parameters must be named parameters (since fields are unordered, it would make it very hard to know where the values would "land"). So you have to specify the field name you want to update:
user = self.model(phone_number=phone_number)
Related
What is the cause of this error? I got this error after changing the
admin style 'User' object has no attribute 'get_all_permissions' plz help me. (What is the cause of this error? I got this error after changing the
admin style 'User' object has no attribute 'get_all_permissions' plz help me. )
class UserManager(BaseUserManager):
def create_user(self, email, username, full_name, phone, password):
if not email:
raise ValueError('plz input email')
if not username:
raise ValueError('plz input username')
if not full_name:
raise ValueError('plz input full_name')
if not phone:
raise ValueError('plz input phone')
user = self.model(email=self.normalize_email(email), username=username, full_name=full_name, phone=phone)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, full_name, phone, password):
user = self.create_user(email, username, full_name, phone, password)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=50, unique=True)
username = models.CharField(max_length=100, null=True, blank=True, unique=True)
full_name = models.CharField(max_length=300)
phone = models.CharField(max_length=15)
address = models.CharField(max_length=500)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
permission = models.ManyToManyField(Permission, related_name='users')
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'full_name', 'phone']
objects = UserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_superuser
def has_module_perms(self, app_label):
return self.is_superuser
#property
def is_staff(self):
return self.is_admin
Add these codes to your model.py
Import PermissionsMixin from Django contrib Auth
from django.contrib.auth.models import PermissionsMixin
Then change
class Account(AbstractBaseUser):
to
class Account(AbstractBaseUser, PermissionsMixin):
Then it will work fine
Instead of returning self.is_superuser,
return self.is_admin
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
will work I hope. :-) It's been one and half a year.
I'm using Django REST with the rest_auth package, and I'm having an issue with serializing custom fields when registering a new user.
The field "is_employer" is always set to false even when you set it to true. Also in the API if you set the is_employer checkbox to true, it doesn't change anything. I added it in models, serializers and adapter, what am I missing?
MODELS:
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser):
username = None
first_name = None
last_name = None
email = models.EmailField(verbose_name='email address', max_length=255, 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)
is_employer = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = MyUserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(selfself, app_label):
return True;
SERIALIZERS:
from django.contrib.auth.hashers import make_password
from rest_framework import serializers
from rest_auth.registration.serializers import RegisterSerializer
from users.models import CustomUser
class CustomRegisterSerializer(RegisterSerializer):
def get_cleaned_data(self):
data_dict = super().get_cleaned_data()
data_dict['is_employer'] = self.validated_data.get('is_employer', '')
return data_dict
ADAPTER:
class CustomAccountAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=False):
user = super().save_user(request, user, form, commit)
data = form.cleaned_data
user.is_employer = data.get('is_employer')
user.save()
return user
First, set the is_employer field explicitly in the CustomRegisterSerializer class
from rest_auth.registration.serializers import RegisterSerializer
class CustomRegisterSerializer(RegisterSerializer):
is_employer = serializers.BooleanField(default=True)
def get_cleaned_data(self):
data_dict = super().get_cleaned_data()
data_dict['is_employer'] = self.validated_data.get('is_employer', False)
return data_dict
then in your settings.py update the serializer as
# settings.py
REST_AUTH_REGISTER_SERIALIZERS = {
"REGISTER_SERIALIZER": "dotted.path.to.CustomRegisterSerializer"
}
the code below is a simple register for an account now when I submit this form it redirects me to the home page and this means that my form is valid and works but when I check my Admin page I see that account is not registered and I get no error. therefor I can understand here that my code is already working but it hasn't been saved.
so, how can I save member through FormView?
thanks in advance
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.generic import TemplateView, View
from django.views.generic.edit import FormView, CreateView
from .forms import UserForm
from .models import User
from django.urls import reverse_lazy
class IndexView(TemplateView):
template_name = "accounts/index.html"
class ProfileView(CreateView):
template_name = 'accounts/register.html'
success_url = reverse_lazy('accounts:index')
form_class = UserForm
forms.py
from django import forms
from .models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label="Confirm Password", widget=forms.PasswordInput)
class Meta:
model = User
fields = '__all__'
exclude = ('staff', 'active', 'admin', 'last_login')
def clean_password2(self):
password = self.cleaned_data['password']
password2 = self.cleaned_data['password2']
if password and password2 and password != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def clean_email(self):
email = self.cleaned_data['email']
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
models.py
from django.db import models
from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager)
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserManager(BaseUserManager):
def create_user(self, email, password, username, is_staff=True, is_admin=True, is_active=True):
if not email:
raise ValueError("This email is invalid")
if not password:
raise ValueError("This Password is invalid")
if not username:
raise ValueError("This Username is invalid")
user = self.model(
email=self.normalize_email(email)
)
user.staff = is_staff
user.admin = is_admin
user.active = is_active
user.set_password(password)
user.username = username
user.save(using=self._db)
return user
def create_staffuser(self, email, password, username):
user = self.create_user(
email,
password=password,
username=username,
is_staff=True,
)
return user
def create_superuser(self, email, password, username):
user = self.create_user(
email=email,
password=password,
username=username,
is_staff=True,
is_admin=True,
)
return user
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True, verbose_name="Email")
first_name = models.CharField(max_length=255, verbose_name="First Name")
last_name = models.CharField(max_length=255, verbose_name="Last Name")
username = models.CharField(max_length=50, unique=True, verbose_name="Username")
active = models.BooleanField(default=True, verbose_name="Active")
staff = models.BooleanField(default=False, verbose_name="Staff")
admin = models.BooleanField(default=False, verbose_name="Admin")
timestamp = models.DateTimeField(auto_now_add=True, verbose_name="Time Stamp")
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
objects = UserManager()
def __str__(self):
return self.username
def get_short_name(self):
return self.username
def get_full_name(self):
return self.username
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
article = models.TextField(blank=True, max_length=500, verbose_name="Article")
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = User.objects.create(user=kwargs['instance'])
post_save.connect(receiver=create_profile, sender=User)
Because a FormView doesn't save() the form. It's meant to be used with any form, not just ModelForms. Not every Form has a save() method.
The only thing the FormView does in form_valid() is redirect to the success url. You have to tell it yourself what you it to do after the form was verified to be valid:
def form_valid(self, form):
form.save()
return super().form_valid(form)
You can see the inner workings of FormView here.
You could use a CreateView instead of a FormView. That would do the saving for you.
I have the error with this models.py ?
This replace built-in User model.
Errors are detected in line user_obj.save(using=self._db) in def UserManager
and in line def create_superuser user = self.create_user(
email,
last_name=last_name,
first_name=first_name,
password=password,
)
It seems like it does not like my timestamp attribute with date value ?
thanks
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class UserManager(BaseUserManager):
def create_user(self, email, last_name, first_name, password=None, is_active=True, is_staff=False, is_admin=False):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
if not password:
raise ValueError('Users must have a password')
user_obj = self.model(
email=self.normalize_email(email),
)
user_obj.set_password(password) # change user password
user_obj.first_name = first_name
user_obj.last_name = last_name
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj
def create_staffuser(self, email, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email,last_name, first_name, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
email,
last_name=last_name,
first_name=first_name,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
first_name = models.CharField(max_length=255, blank=False, null=False)
last_name = models.CharField(max_length=255, blank=False, null=False)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
timestamp = models.DateTimeField(default=timezone.now)
confirmedEmail = models.BooleanField(default=False) # Check if user is valid
confirmedDate = models.DateTimeField(default=False) # Check if user is valid
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name'] # Email & Password are required by default.
def get_full_name(self):
# The user is identified by their email address
return "%s %s" % (self.first_name, self.last_name)
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
return self.email
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_staff(self):
"Is the user a member of staff?"
return self.staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.admin
#property
def is_active(self):
"Is the user active?"
return self.active
objects = UserManager()
I find the issue.
confirmedDate = models.DateTimeField(default=False)
It cannot be default= false as it is a datefield. Good answer is:
confirmedDate = models.DateTimeField(null=True, blank=True)
I know there are similar questions like this, and I tried every solution that is adressed in those questions. Here is my problem described;
When I execute createsuperuser, I got an error as follows;
AttributeError: 'Manager' object has no attribute 'get_by_natural_key'
Here is how I define UserAccountManager and UserAccount in my implementation;
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
class UserAccountManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
if not email:
raise ValueError('Email must be set!')
user = self.model(email=email, first_name=first_name, last_name=last_name)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, first_name, last_name, password):
user = self.create_user(email, first_name, last_name, password)
user.is_admin = True
user.save(using=self._db)
return user
def get_by_natural_key(self, email_):
return self.get(code_number=email_)
class UserAccount(AbstractBaseUser):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
is_active = models.BooleanField(default=True) # default=False when you are going to implement Activation Mail
is_admin = models.BooleanField(default=False)
objects = UserAccountManager
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
def get_short_name(self):
return self.email
def get_full_name(self):
return self.email
def has_perms(self, perm, ob=None):
return True
def has_module_perms(self, app_label):
return True
def natural_key(self):
return self.email
#property
def is_staff(self):
self.is_admin
I set object as follows in UserAccount class : objects = UserAccountManager
What do I do wrong?
Edit (to address Iain Shelvington's solution):
in settings.py, I have this line;
AUTH_USER_MODEL = 'accounts.UserAccount'
It should be objects = UserAccountManager()
https://docs.djangoproject.com/en/1.10/topics/db/managers/#custom-managers-and-model-inheritance
You need to change the setting AUTH_USER_MODEL to 'your_app.UserAccount'