I'm trying to test the creation of an user in Django. But my user model is not the standard one (email is the username).
models.py
from django.contrib.auth.models import AbstractUser, UserManager as AbstractUserManager
class UserManager(AbstractUserManager):
def create_user(self, email, password=None, is_active=True, is_staff=False, is_admin=False):
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
class CustomUser(AbstractUser):
objects = UserManager()
username = None
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
tests.py
from django.contrib.auth import get_user_model
class CustomUserTests(TestCase):
def test_create_user(self):
user = get_user_model()
utilisateur = user.create_user(
email='test#tester.com',
password='testpass123',
)
self.assertEqual(utilisateur.email, 'test#tester.com')
Error
line 10, in test_create_user
utilisateur = user.create_user( AttributeError: type object 'CustomUser' has no attribute 'create_user'
Something is missing but I don't know how to test well this...
Thanks a lot
CustomUser' has no attribute 'create_user'
create_user is not present on the CustomUser model and that's what the error is saying. The method is present on the UserManager and the manager is defined on the user model as objects = UserManager().
So to access the method, you need to use user.objects.create_user.
Related
I can't seem to figure out why my unit test is failing for the following
Traceback (most recent call last):
File "/app/core/tests/test_admin.py", line 26, in test_users_listed
self.assertContains(res, self.user.name)
AttributeError: 'AdminSiteTests' object has no attribute 'user'
test_admin.py
from django.test import TestCase, Client
from django.contrib.auth import get_user_model
from django.urls import reverse
class AdminSiteTests(TestCase):
def setup(self):
self.client = Client()
self.admin_user = get_user_model().objects.create_superuser(
email='admin#test.com',
password='test123'
)
self.client.force_login(self.admin_user)
self.user = get_user_model().objects.create_user(
email='test#test.com',
password='test123',
name='test name'
)
def test_users_listed(self):
"""Test that users are listed on user page"""
url = reverse('admin:core_user_changelist')
res = self.client.get(url)
self.assertContains(res, self.user.name)
self.assertContains(res, self.user.email)
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from core import models
class UserAdmin(BaseUserAdmin):
ordering = ['id']
list_display = ['email', 'name']
admin.site.register(models.User, UserAdmin)
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
"""Creates and saves a new user"""
if not email:
raise ValueError('Users must have a email address')
user = self.model(email=self.normalize_email(email), **extra_fields)
# Must encrypt password using set_password() that comes with BaseUserManager
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""Creates and saves new superuser"""
user = self.create_user(email, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model that supports using email instead of username"""
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
I am creating the user in the setup function for the rest of my tests but I'm thinking maybe the setup function isn't getting called to create the user?
All other tests are passing. Including a test that checks whether a user has been created. Any help would be apperciated
I have created a model class which extends from AbstractUser to handle token authentication, how do I get date_joined property of the modal's object when querying it in django rest framework views.py?
Models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
from .managers import CustomUserManager
# Create your models here.
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
date_of_birth = models.DateField(blank=True, null=True)
def __str__(self):
return self.email
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False, blank=True, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
def __str__(self):
return self.title
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
Here is my Managers.py
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
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()
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)
This my drf view:
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def report2(request):
user_data = CustomUser.objects.get(id=request.user.id)
print("User data ",user_data)
return Response("date_joined", status=status.HTTP_200_OK)
The user_data only returns email_id, I expect it to return all the attributes of the table including date_joined.
Below is an image from my database:
Kindly someone guide me, how can I get date_joined attribute of the CustomUser object in my view function?
Thanks
This is my model class
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager
class UserProfileManager(BaseUserManager):
"""Helps Djamgo work with our custom user model"""
def create_user(self,email,name,password=None):
if not email:
raise ValueError('users must have an email address')
#normalizing the email address convert it to the lowercase
email = self.normalize_email(email)
user = self.model(email=email, name=name)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email,name,password):
user = self.create_user(email,name,password)
user.is_superuser =True
user.is_staff = True
class UserProfile(AbstractBaseUser,PermissionsMixin):
email = models.EmailField(max_length=255,unique = True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
related_name = "+"
object = UserProfileManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ['name']
#helper funtionality
def full_name(self):
"""Use to get full name of the user"""
return self.name
def short_name(self):
"""Use to get short name name of the user"""
return self.name
def __str__(self):
`enter code here`return self.email
My setting.py contains everything
and my db is sync and I have already created a superuser. When I am trying to access my admin from admin login page it gives an error "please login with correct email password " But I have already ensured 5 times that I am using correct email password!
Is there any way to implement form only with email field (without password and username)? User will receive email with link to confirm his account and set password.
Any information will be helpfull, thanks.
To user Temka:
I've already have cutom RegistrationForm:
from registration.forms import RegistrationForm
class UserForm(RegistrationForm):
username = forms.CharField(
max_length=254,
required=False,
widget=forms.HiddenInput(),
)
password1 = forms.CharField(
widget=forms.HiddenInput(),
required=False,
)
password2 = forms.CharField(
widget=forms.HiddenInput(),
required=False,
)
def clean_email(self):
email = self.cleaned_data['email']
self.cleaned_data['username'] = email
return email
def clean_password2(self):
pass
Also thanks for "unusable password" info.
User model
First you need to create custom User manager and model.
Documentation can be found here https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#a-full-example
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class EmailUserManager(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, password=password,)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class EmailUser(AbstractBaseUser, PermissionsMixin):
email = EmailField(
verbose_name='email',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
objects = EmailUserManager()
USERNAME_FIELD = 'email'
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def __str__(self):
return self.email
#property
def is_staff(self):
return self.is_admin
And register it in your settings.py with this line AUTH_USER_MODEL = 'app.EmailUser'.
Now your EmailUser model can be used with from django.contrib.auth import get_user_model and from django.conf.settings import AUTH_USER_MODEL.
Example usage (foreign key):
from django.db import models
from django.conf.settings import AUTH_USER_MODEL
class Profile(models.Model):
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
user = models.OneToOneField(AUTH_USER_MODEL, verbose_name='User',
related_name='profile')
full_name = models.CharField('Full name', max_length=64, blank=False)
phone = models.CharField('Phone', max_length=64, blank=True)
Registration
When using django-registration-redux two-step registration:
Create User with None password on registration. This will make User model with unusable password https://docs.djangoproject.com/es/1.9/ref/contrib/auth/#django.contrib.auth.models.User.has_usable_password. It may be necessary to create custom RegistrationForm and RegistrationView to avoid password checking.
On activation form submit (activation form template with password field) use methods RegistrationManager.activate_user(key) and User.set_password(password)
I've created a CustomUser from AbstractUser in Django 1.9. Add on admin.sites.register when I was create superuser, django have created successful but when I was log in on system the user didn't exists.
Follow the code:
On customuser/models.py:
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomUserManager(BaseUserManager):
def create_user(self, username, email, first_name, last_name, cpf, password=None):
user = self.model(
username=username,
email=email,
first_name=first_name,
last_name=last_name,
cpf=cpf
)
return user
def create_superuser(self, username, email, first_name, last_name, cpf, password):
user = self.create_user(username, email, first_name, last_name, cpf,
password=password)
user.is_super_user = True
user.save()
return user
class CustomUser(AbstractUser):
SEXO_CHOICES = (
(u'Masculino', u'Masculino'),
(u'Feminino', u'Feminino'),
)
cpf = models.BigIntegerField(unique=True)
phone = models.CharField(max_length=15, blank=True)
is_super_user = models.BooleanField(default=False)
data_de_nascimento = models.DateField(null=True)
sexo = models.CharField(max_length=9, null=True, choices=SEXO_CHOICES)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name', 'cpf']
objects = CustomUserManager()
On settins.py, I add the line:
INSTALLED_APPS = [
...
'customuser',
]
...
AUTH_USER_MODEL = 'customuser.CustomUser'
And my customuser/admin.py:
from django.contrib import admin
from models import CustomUser, CustomUserManager
admin.site.register(CustomUser)
Thanks a lot for your help.
See these docs on making custom user work with admin site.
UPDATE:
Sorry, previously I thought, you were inheriting your model from AbstractBaseUser, therefore that answer was giving you error.
Since, you're inheriting from AbstractUser, your subclass will automatically get is_staff field. So, you'll just need to set is_staff to True in create_superuser method.
class CustomUserManager(...):
# ...
def create_superuser(...):
# ...
user.is_staff = True
user.save()
return user