I created a register/login system through DRF by overriding dj_rest_auth
If registering an user with Postman, by firing on the endpoint, that user can be used for login through endpoint
However, if creating an user through Django Admin, that user cannot be used for login through endpoint, and notably, if seen through Django Admin, the password is not hashed
How to handle this?
serializers.py
class CustomLoginSerializer(LoginSerializer):
def validate_auth_user_status(self, user):
request = self.context.get('request')
if not request.data.get('role'):
msg = 'Role is missing from the payload.'
raise exceptions.ValidationError(msg)
if not user.groups.filter(name=request.data.get('role')).exists():
msg = 'Invalid role for the user.'
raise exceptions.ValidationError(msg)
def create(self, validated_data):
pass # Empty because the function is not needed
# but Pylint demanded to implement it anyway
def update(self, instance, validated_data):
pass # Empty because the function is not needed
# but Pylint demanded to implement it anyway
class CustomRegisterSerializer(RegisterSerializer):
name = serializers.CharField()
def get_cleaned_data(self):
super().get_cleaned_data()
return {
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'name': self.validated_data.get('name', '')
}
def create(self, validated_data):
pass # Empty because the function is not needed
# but Pylint demanded to implement it anyway
def update(self, instance, validated_data):
pass # Empty because the function is not needed
# but Pylint demanded to implement it anyway
def save(self, request):
user = super().save(request)
user.name = self.get_cleaned_data().get('name')
user.save()
client_role, _created = Group.objects.get_or_create(name='client')
user.groups.add(client_role)
return user
urls.py
urlpatterns = [
path('auth/registration/', include('dj_rest_auth.registration.urls')),
path('auth/', include('dj_rest_auth.urls')),
path('auth/user-login/', CustomLoginView.as_view(), name='custom_user_login'),
path('auth/google/', GoogleView.as_view(), name='google'),
]
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
name = models.CharField(max_length=100)
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
diet_profile = models.OneToOneField(
DietProfile,
on_delete=models.CASCADE,
primary_key=False,
related_name="user",
blank=True, null=True
)
nutritionist = models.ForeignKey(
Nutritionist,
on_delete=models.CASCADE,
related_name="clients",
blank=True,
null=True
)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return str(self.email)
EDIT:
adding custom user manager and admin.py
manager.py
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
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()
client_role, _created = Group.objects.get_or_create(name='client')
user.groups.add(client_role)
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
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)
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
admin.site.register(CustomUser)
Related
I am using Django as backend for my mobile app. When creating users info I need the following info:name, DoB and firebaseUID. Please note that I do not want their email or password. But I want to create superusers who act as admins and want the superusers to be created using email and password. So I am not sure if I have to:
Create a custom user by extending AbstractBaseUser and have a user manager attached to that custom user OR
Create a custom user by extending AbstractBaseUser and then create another Django user class which is only for superusers.
I implemented option 1 with the below code, but I get the following error: "TypeError: MyUserManager.create_superuser() missing 1 required positional argument: 'email'" Also when I am creating superuser, Django is asking for name, firebaseUID and DOB fields although I want to create superusers only email and password fields.
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.utils import timezone
class MyUserManager(models.Manager):
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', 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)
def get_by_natural_key(self, email):
return self.get(email=email)
class CustomUser(AbstractBaseUser):
name = models.CharField(null=True, blank=True, max_length=100)
userName = models.CharField(
null=True, blank=True, max_length=100, unique=True)
firebaseUid = models.CharField(
null=True, blank=True, max_length=100, unique=True)
dob = models.DateField(max_length=8)
created_at = models.DateTimeField(default=timezone.now)
email = models.EmailField(unique=True) #used only for createing super user at this point
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
# countryCode = models.CharField(null=True, blank=True, max_length=5)
USERNAME_FIELD = 'userName'
REQUIRED_FIELDS = ['name', 'firebaseUid', 'dob']
objects = MyUserManager()
def __str__(self):
return self.userName
def get_fBaseUid_name(self):
return self.firebaseUid
def has_perm(self, perm, obj=None):
return self.is_superuser
def has_module_perms(self, app_label):
return self.is_superuser
Please let me know if you need any other info. Thank you in advance!
Edit: I already added the following in my settings.py file
AUTH_USER_MODEL = "accounts.CustomUser"
AUTHENTICATION_BACKENDS = ['accounts.backends.FirebaseBackend']
Tl;dr: I want regular users to be created using different fields than creating a superuser.
Has your User model been specified in your settings.py?
If it hasn't, specify it
AUTH_USER_MODEL = "yourapp.UserModel"
Also, in your CustomUser model
Do this
# For creating a superuser using Django
REQUIRED_FIELDS = []
And if you want to create users with "email" and "password", not "username" and "password"
Do this
USERNAME_FIELD = "email"
You can use this code for your create_superuser as well
def create_superuser(self, email, password=None):
if password is None:
raise TypeError("Password should not be none")
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
I hope that helps
a pretty noob here. I am trying to create a user profile at the time when the account is created using signals. I want all the fields of the user profile to be filled in sign up page.
This is the user profile that I am trying to populate:
class UserProfile(models.Model):
user = models.ForeignKey(get_user_model(), verbose_name='user', on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True)
contact_number = models.CharField(max_length=11, default="0331232132")
def __str__(self):
return self.name
This is my custom user model here:
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, **kwargs):
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **kwargs)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **kwargs):
kwargs.setdefault("is_staff", False)
kwargs.setdefault("is_superuser", False)
return self._create_user(email, password, **kwargs)
def create_superuser(self, email, password=None, **kwargs):
kwargs.setdefault("is_staff", True)
kwargs.setdefault("is_superuser", True)
if kwargs.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if kwargs.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **kwargs)
class User(AbstractUser):
username = None
email = models.EmailField(_("email address"), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
This is my user creation form that I am sending to template:
class CustomUserCreationForm(UserCreationForm):
password2 = forms.CharField(
label=_("Confirm Password"),
widget=forms.PasswordInput,
)
name = forms.CharField()
contact_number = forms.CharField(
max_length=11
)
class Meta:
model = get_user_model()
fields = ['email']
I am not sure if it is relevant but this is my custom email backend.
class EmailBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = User.objects.get(email__iexact=username)
except User.DoesNotExist:
return None
except User.MultipleObjectsReturned:
return User.objects.filter(email=username).order_by('id').first()
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
Now what I want is when the user submits the user creation form, Email and Password field is used to create a user account while name and contact number along with the newly created user object are used to create a userprofile instance using signals. All the examples that I have seen till now only handle setting only the user object in profile.
I am building a custom User class in django to use in creating a signup application and I keep on getting the error above every time I try to makemigrations.As far as I can see, my code is per django documentation here.I also have AUTH_USER_MODEL correctly placed in my settings configurations. Here's my models.py
# from __future__ import unicode_literals
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.validators import RegexValidator
class UserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
if password:
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
"""Create and save a regular User with the given email and password."""
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', 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 User(AbstractUser):
email = models.EmailField(_('email address'), unique=True, default='email')
username = None
first_name = models.CharField(max_length=20, blank=False, null=False, default='first_name')
last_name = models.CharField(max_length=20, blank=False, null=False, default='last_name')
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+91 ...'")
phone_no = models.CharField(validators=[phone_regex], max_length=17,blank=False, default='phone_number')
# email_validator = EmailValidator(message='Invalid email
# address',code=None,whitelist=None)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
# Email & Password are required by default
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
objects = UserManager()
def get_full_name(self):
return self.email
def get_short_name():
return self.email
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
# does user have a specific permission
return True
def has_module_pers(self, app_label):
# does user have permissions to view the app 'app_label'
return True
#property
def is_admin(self):
return self.is_admin
#property
def is_active(self):
return self.is_active
# Create your models here.""
I removed the existing users from Database and deleted the previous migration files from migration folder. After again migrations issue has been resolved
I am trying to create customuser for my Django project with email as username and add a radio button for truck and company. so that in the registration process email-id will be registered as per truck or company. I mentioned the radio button as 'Tag' and add a ManytoMany field to Tag in EmailUser model. When i do makemigrations, it was raising an error : (fields.E300) Field defines a relation with model 'AbstractEmailUser' which is either not installed, or is abstract.
I am quite new to Django and not sure whether I have created a correct code for what I really wants. Please help me solving this.
here is my code,
models.py:
import django
from django.contrib.auth.models import (
AbstractBaseUser, BaseUserManager, PermissionsMixin)
from django.core.mail import send_mail
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
class EmailUserManager(BaseUserManager):
"""Custom manager for EmailUser."""
def _create_user(self, email, password,
is_staff, is_superuser, **extra_fields):
"""Create and save an EmailUser with the given email and password.
:param str email: user email
:param str password: user password
:param bool is_staff: whether user staff or not
:param bool is_superuser: whether user admin or not
:return custom_user.models.EmailUser user: user
:raise ValueError: email is not set
"""
now = timezone.now()
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
is_active = extra_fields.pop("is_active", True)
user = self.model(email=email, is_staff=is_staff, is_active=is_active,
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, email, password=None, **extra_fields):
"""Create and save an EmailUser with the given email and password.
:param str email: user email
:param str password: user password
:return custom_user.models.EmailUser user: regular user
"""
is_staff = extra_fields.pop("is_staff", False)
return self._create_user(email, password, is_staff, False,
**extra_fields)
def create_superuser(self, email, password, **extra_fields):
"""Create and save an EmailUser with the given email and password.
:param str email: user email
:param str password: user password
:return custom_user.models.EmailUser user: admin user
"""
return self._create_user(email, password, True, True,
**extra_fields)
class AbstractEmailUser(AbstractBaseUser, PermissionsMixin):
"""Abstract User with the same behaviour as Django's default User.
AbstractEmailUser does not have username field. Uses email as the
USERNAME_FIELD for authentication.
Use this if you need to extend EmailUser.
Inherits from both the AbstractBaseUser and PermissionMixin.
The following attributes are inherited from the superclasses:
* password
* last_login
* is_superuser
"""
email = models.EmailField(_('email address'), max_length=255,
unique=True, db_index=True)
is_staff = models.BooleanField(
_('staff status'), default=False, help_text=_(
'Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True, help_text=_(
'Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = EmailUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True
# def __init__(self, *args, **kwargs):
# super(AbstractEmailUser, self).__init__(*args, **kwargs)
# if self.instance.pk:
# self.fields['Tag'].initial = self.instance.Tag_set.all()
def get_full_name(self):
"""Return the email."""
return self.email
def get_short_name(self):
"""Return the email."""
return self.email
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this User."""
send_mail(subject, message, from_email, [self.email], **kwargs)
# Monkey patch Django 1.7 to avoid detecting migrations
if django.VERSION[:2] == (1, 7):
last_login = AbstractEmailUser._meta.get_field('last_login')
last_login.blank = True
last_login.null = True
last_login.default = models.fields.NOT_PROVIDED
groups = AbstractEmailUser._meta.get_field('groups')
groups.help_text = _('The groups this user belongs to. A user will get '
'all permissions granted to each of their groups.')
class EmailUser(AbstractEmailUser):
"""
Concrete class of AbstractEmailUser.
Use this if you don't need to extend EmailUser.
"""
CHOICES = (('Truck', 'Truck'),('Company', 'Company'),)
Tag = models.ManyToManyField(AbstractEmailUser)
class Meta(AbstractEmailUser.Meta):
swappable = 'AUTH_USER_MODEL'
forms.py:
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.utils.translation import ugettext_lazy as _
class EmailUserCreationForm(forms.ModelForm):
"""A form for creating new users.
Includes all the required fields, plus a repeated password.
"""
error_messages = {
'duplicate_email': _("A user with that email already exists."),
'password_mismatch': _("The two password fields didn't match."),
}
password1 = forms.CharField(
label=_("Password"),
widget=forms.PasswordInput)
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput,
help_text=_("Enter the same password as above, for verification."))
CHOICES= (('Truck', 'Truck'),('Company', 'Company'),)
Tag = forms.ChoiceField(choices=CHOICES, label='Tag', widget=forms.RadioSelect())
class Meta:
model = get_user_model()
fields = ('email', 'Tag',)
def clean_email(self):
"""Clean form email.
:return str email: cleaned email
:raise forms.ValidationError: Email is duplicated
"""
# Since EmailUser.email is unique, this check is redundant,
# but it sets a nicer error message than the ORM. See #13147.
email = self.cleaned_data["email"]
try:
get_user_model()._default_manager.get(email=email)
except get_user_model().DoesNotExist:
return email
raise forms.ValidationError(
self.error_messages['duplicate_email'],
code='duplicate_email',
)
def clean_password2(self):
"""Check that the two password entries match.
:return str password2: cleaned password2
:raise forms.ValidationError: password2 != password1
"""
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def save(self, commit=True):
"""Save user.
Save the provided password in hashed format.
:return custom_user.models.EmailUser: user
"""
user = super(EmailUserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class EmailUserChangeForm(forms.ModelForm):
"""A form for updating users.
Includes all the fields on the user, but replaces the password field
with admin's password hash display field.
"""
password = ReadOnlyPasswordHashField(label=_("Password"), help_text=_(
"Raw passwords are not stored, so there is no way to see "
"this user's password, but you can change the password "
"using this form."))
class Meta:
model = get_user_model()
exclude = ()
def __init__(self, *args, **kwargs):
"""Init the form."""
super(EmailUserChangeForm, self).__init__(*args, **kwargs)
f = self.fields.get('user_permissions', None)
if f is not None:
f.queryset = f.queryset.select_related('content_type')
def clean_password(self):
"""Clean password.
Regardless of what the user provides, return the initial value.
This is done here, rather than on the field, because the
field does not have access to the initial value.
:return str password:
"""
return self.initial["password"]
admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext_lazy as _
from .forms import EmailUserChangeForm, EmailUserCreationForm
from .models import EmailUser
class EmailUserAdmin(UserAdmin):
"""EmailUser Admin model."""
fieldsets = (
(None, {'fields': ('email', 'password', 'Tag')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = ((
None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'Tag')
}
),
)
# The forms to add and change user instances
form = EmailUserChangeForm
add_form = EmailUserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'is_staff', )
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups', 'Tag')
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ('groups', 'user_permissions', 'Tag',)
# Register the new EmailUserAdmin
admin.site.register(EmailUser, EmailUserAdmin)
I'm trying to benefit from Django 1.5 and created custom user model. In order to use builtin permissions, which I would like to limit access with in the admin interface. I inherited my user class also from PermissionMixin. But when I create new user and check Staff box, the new user gets all the access that superuser has.
What am I doing wrong?
models.py
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=MyUserManager.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, password=password,)
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, db_index=True,)
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin site.'))
objects = MyUserManager()
USERNAME_FIELD = 'email'
I had the same problem , in my case I had this:
class Estudiante(AbstractBaseUser,PermissionsMixin):
name = models.CharField(max_length=250,null=False,blank=False)
email = models.EmailField(
verbose_name='Direccion de correo Electronico',
max_length=255,
unique=True,
db_index=True,
)
is_staff = models.BooleanField(u'staff status', default=False,
help_text=u'Designates whether the user can log into this admin '
'site.')
is_active = models.BooleanField(u'active', default=True,
help_text=u'Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def get_full_name(self):
# The user is identified by their email address
return self.name
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
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
and MyUserManager:
class MyUserManager(BaseUserManager):
def create_user(self, name,email, password=None):
....
return user
def create_superuser(self, name,email, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.model(
email=MyUserManager.normalize_email(email),
name=name,
)
user.is_staff = True
user.is_active = True
user.is_superuser = True
user.set_password(password)
user.save(using=self._db)
return user
I fixed the problem commented or eliminate the methods "has_perm" and has_module_perms
class Estudiante(AbstractBaseUser,PermissionsMixin):
name = models.CharField(max_length=250,null=False,blank=False)
email = models.EmailField(
verbose_name='Direccion de correo Electronico',
max_length=255,
unique=True,
db_index=True,
)
is_staff = models.BooleanField(u'staff status', default=False,
help_text=u'Designates whether the user can log into this admin '
'site.')
is_active = models.BooleanField(u'active', default=True,
help_text=u'Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.')
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def get_full_name(self):
# The user is identified by their email address
return self.name
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
I've rewritten custom user model. The main difference from the django user model now is that mine does not have username field. Here is the code:
import warnings
from django.core.exceptions import ImproperlyConfigured
from django.core.mail import send_mail
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin,\
SiteProfileNotAvailable, BaseUserManager
from django.utils import timezone
from django.utils.http import urlquote
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
def create_user(self, email=None, password=None, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
now = timezone.now()
if not email:
raise ValueError('The given email must be set')
email = CustomUserManager.normalize_email(email)
user = self.model(email=email,
is_staff=False, is_active=True, is_superuser=False,
last_login=now, date_joined=now, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
u = self.create_user(email, password, **extra_fields)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
middle_name = models.CharField(_('middle name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
def get_absolute_url(self):
return "/users/%s/" % urlquote(self.username)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"Returns the short name for the user."
return self.first_name
def email_user(self, subject, message, from_email=None):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email])
def get_profile(self):
"""
Returns site-specific profile for this user. Raises
SiteProfileNotAvailable if this site does not allow profiles.
"""
warnings.warn("The use of AUTH_PROFILE_MODULE to define user profiles"
" has been deprecated.",
PendingDeprecationWarning)
if not hasattr(self, '_profile_cache'):
from django.conf import settings
if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
raise SiteProfileNotAvailable(
'You need to set AUTH_PROFILE_MODULE in your project '
'settings')
try:
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
except ValueError:
raise SiteProfileNotAvailable(
'app_label and model_name should be separated by a dot in '
'the AUTH_PROFILE_MODULE setting')
try:
model = models.get_model(app_label, model_name)
if model is None:
raise SiteProfileNotAvailable(
'Unable to load the profile model, check '
'AUTH_PROFILE_MODULE in your project settings')
self._profile_cache = model._default_manager.using(
self._state.db).get(user__id__exact=self.id)
self._profile_cache.user = self
except (ImportError, ImproperlyConfigured):
raise SiteProfileNotAvailable
return self._profile_cache
Now it works and keeps all default permissions. Also note, that for the admin you must rewrite user ModelAdmin and UserCreationForm along with UserChangeForm classes.
Still relevant |
I had the same problem, only superuser had all permissions.Even if I create staff and assign them permissions, I could log-in using that account but it showed "you dont have permissions to edit or view anything".
But removing "has_perm" and "has_module_perms" from custom user class fixed it.
Thank you