Abstract base manager isn't accessible - python

I'm trying to create a new user, but I get this message:
_get_
raise AttributeError("Manager isn't accessible via %s instances" % type._name_)
AttributeError: Manager isn't accessible via CompanyUser instances
This is what I'm doing:
def obj_create(self, bundle, request=None, **kwargs):
try:
bundle = super(AccountCreateResource, self).obj_create(bundle)
bundle.obj.set_password(bundle.data.get('password'))
bundle.obj.objects.create_user()
except IntegrityError:
raise BadRequest('Username already exists')
I should beable to access the manager. This is my model:
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):
def create_user(self, email, password=None, **extra_fields):
"""
Creates and saves an EmailUser with the given email and password.
"""
now = timezone.now()
if not email:
raise ValueError('The given email must be set')
email = EmailUserManager.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):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(email, password, **extra_fields)
user.is_staff = True
user.is_active = True
user.is_superuser = True
user.save(using=self._db)
return user
class AbstractEmailUser(AbstractBaseUser, PermissionsMixin):
"""
Abstract User with the same behaviour as Django's default User but
without a 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:
abstract = True
def get_full_name(self):
"""
Returns the email.
"""
return self.email
def get_short_name(self):
"""
Returns the email.
"""
return self.email
def email_user(self, subject, message, from_email=None):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email])
class CompanyUser(AbstractEmailUser):
"""
Concrete class of AbstractEmailUser.
"""
company = models.CharField(max_length=100)
pass

You don't show enough of the code or the traceback to understand what's really going on, but anyway: the error message you get means you tried to access the Manager from an instance, and it's not allowed, period - the fact that you have an abstract model is totally irrelevant. You have to access the Manager from the model class itself. Hopefully it's just a matter of replacing instance.objects by type(instance).objects.

It's really not clear what you are trying to do here. This line - the one that's causing the error - makes no sense:
bundle.obj.objects.create_user()
Since you haven't provided the code for bundle, I have to guess that this is a model with an obj ForeignKey, which points to CompanyUser (rather strange naming conventions, though). But as the error says, you can't call objects on an instance, only on the class. But even if you could, the line still doesn't make sense: obj is already a User, so why would you want to create one? And again, create_user takes at least an email parameter, which you're not supplying.

Related

Django Custom User Manager Unit Test - NoneType object is not callable

This all started when I downloaded coverage.py and started testing my django project. Everything is fine, however I'm lacking coverage on a custom user manager I set up in Models.py
Here's the full code.
models.py
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _
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)
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 CustomUser(AbstractUser):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
# profile_image = models.ImageField(upload_to="users/profile_pic", blank=True)
is_pastor = models.BooleanField(default=True)
home_church = models.ForeignKey(
'church.Church',
on_delete="CASCADE",
blank=True,
null=True)
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager() ## This is the new line in the User model. ##
I'm attempting to test the "_create_user" function in the UserManager. Here is my code
test.py
class UserManagerTestCase(TestCase):
def test_main_create_user(self):
manager = UserManager()
user = manager._create_user('jdoe#gmail.com', 'password123')
self.assertTrue(isinstance(user, User))
Unfortunately, when I call the '_create_user' function I get a Type Error: 'NoneType' object is not callable.
This is strange, because the model manager works as expected when creating users and I confirmed with print statements that both the email and **extra_fields arguments are not None.
Some research online said this might because the Manager is not designed to be called directly. Is that the case? If so, how should you handle unit testing?
Instantiate CustomUser() with values so it can be used to access the methods to be tested.
UserManager CANNOT be used directly, it is only accessible through the
Model it was created for: CustomUser.
#tests.py
class UserManagerTestCase(TestCase):
def test_main_create_user(self):
user = CustomUser.objects.create_user('jdoe#gmail.com', 'password123')
self.assertTrue(isinstance(user, User))

Custom user model not working on django admin

I created an app authentication, code for models is,
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import BaseUserManager
from django.db import models
class AccountManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
if not email:
raise ValueError('Users must have a valid email address.')
account = self.model(email=self.normalize_email(email))
account.set_password(password)
account.save()
return account
def create_superuser(self, email, password, **kwargs):
account = self.create_user(email, password, **kwargs)
account.is_admin = True
account.save()
return account
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
# username = models.CharField(max_length=40, 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)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
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
apart from this the changes that i did was added authentication in INSTALLED_APPS and in settings added AUTH_USER_MODEL = 'authentication.Account'
When i create a super-user from shell, its working and inserting in db, but when i try to login into the django admin console,
initially the error was is_staff not found, which i added. Now it is showing invalid username and password for all. I tried that a couple of time generating new one each time. What am i doing wrong ?
EDIT
I am adding the dbs dump that i used to validate if the user was created
sqlite> select * from authentication_account;
1|pbkdf2_sha256$24000$ZRHCXpUI3w0G$fh4z9y5vmYAZ0FEiDr908dJD3ezw62nm3lpkZxUi/Es=||me#rahulbhola.in|||1|0|2016-05-28 21:15:59.292988|2016-05-28 21:15:59.415382
Still login in django defaut admin does not work
You added the is_staff later on which seems to be false by default, so when you migrated the field was created in database with the value false in the is_staff field.
Please make the changes as below and try
class AccountManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
if not email:
raise ValueError('Users must have a valid email address.')
account = self.model(email=self.normalize_email(email))
account.set_password(password)
account.save(using=self.db)
return account
def create_superuser(self, email, password, **kwargs):
account = self.create_user(email, password, **kwargs)
account.is_staff = True
account.is_admin = True
account.save(using=self.db)
return account
Please not account.save(using=self.db) in the code above and account.is_staff = True in the create admin method.
Please try creating the new user again i prefer using the shell ( python manage.py shell)
from authentication.models import Account
user = Account()
user.create_superuser(username='some_username', password='some_password')
user.save()
Now that the user is created please try logging in using the django admin.
This should work. I had similar issues which is fixed and i am able to create user and login from django admin.
I am assuming that you have created the custom authentication backend already, if not please create
Hope this helps you.

Why isn't my password being secured when using a custom user model in Django?

I am trying to build a custom user model in Django. My models.py looks like this:
class UserManager(BaseUserManager):
def _create_user(self, username, email, password, is_staff, is_superuser, **extra_fields):
now = timezone.now()
if not username:
raise ValueError(_('The given username must be set'))
if not email:
raise ValueError(_('The given email must be set'))
email = self.normalize_email(email)
user = self.model(
username=username, email=email,
is_staff=is_staff, is_active=False,
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, username, email, password=None, **extra_fields):
return self._create_user(username, email, password, False, False, **extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
user=self._create_user(username, email, password, True, True, **extra_fields)
user.is_active=True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
# Standard fields
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and #/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'), _('Enter a valid username.'), _('invalid'))
])
first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True)
email = models.EmailField(_('email address'), max_length=255)
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)
# Custom fields
is_publisher = models.BooleanField(_('publisher status'), default=False)
# User manager
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def email_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
Anyway, if I create a super user using the createsuperuser command, everything works fine : the user is created, and the password is hashed properly and secured. However, if I create a user from my admin panel, the user created has his/her password completely exposed. Also the confirm password field doesn't show up, which it does in the regular user model used in Django. How can I solve this problem?
Also, yes I do have AUTH_USER_MODEL = 'myapp.User' in my settings.py.
You need a custom ModelForm and ModelAdmin for creating/ updating User model items.
See: Custom User Models with Admin Site
def home(request):
if request.method == 'POST':
uf = UserForm(request.POST, prefix='user')
upf = UserProfileForm(request.POST, prefix='userprofile')
if uf.is_valid() * upf.is_valid():
userform = uf.save(commit=False)
userform.password = make_password(uf.cleaned_data['password'])
userform.save()
messages.success(request,
'successful Registration',
extra_tags='safe')
else:
uf = UserForm(prefix='user')
return render_to_response('base.html',
dict(userform=uf
),
context_instance=RequestContext(request))
In your views.py try to use this and in forms.py try to get the password from django form. Hope this works
A form with no custom code, and direct access to password field, writes directly on the password field. No call is made to createuser or createsuperuser, so set_password is never called (by default, a ModelForm calls save in the model when called save in it). Recall that writing the user password does not write a secure password (that's why createuser and createsuperuser call set_password somewhere). To do that, avoid writing directly on the field but, instead, calling:
myuserinstance.set_password('new pwd')
# not this:
# myuserinstance.password = 'new pwd'
So you must use custom logic in a custom form. See the implementation for details; you will notice those forms have custom logic calling set_password and check_password. BTW default UserAdmin in Django creates a user in TWO steps: user/password/password_confirm (such password creates), and then whole user data. There's a very custom implementation for that.

How to custom user models in django 1.5

As we all know, django provide an strong User and Authenticate app.
as usually, there is two way to custom the user
use OneToOneField way . we can define a model profile which keep some user information fields. we also can use get_profile method to get the profile. but,there is a problem, if
we get the user profile, we must join the data table. some code demo:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
use AbstractBaseUser, PermissionsMixin . we can custom the user by change the AbstractBaseUser, PermissionsMixin in django--1.5, and must define the UserAdmin.the document:https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#extending-the-existing-user-model
I am very confused and do not know which way is better?
You have to do is add AUTH_USER_MODEL to settings with path to custom user class, which extends either AbstractBaseUser (more customizable version) or AbstractUser.
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
u = self.create_user(username,
password=password,
date_of_birth=date_of_birth
)
u.is_admin = True
u.save(using=self._db)
return u
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def get_full_name(self):
# The user is identified by their email address
return self.email
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
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
The best way to do this now since Django 1.5 is with custom user models, setting AUTH_USER_MODEL to your user model.
There's no reason to be confused. The docs you link to are correct: you should extend AbstractBaseUser.
Also, you should upgrade to version 1.6.

Django: TypeError: 'is_active' is an invalid keyword argument for this function

I keep receiving this error when I try to create a user via the createsuperuser management command:
TypeError: 'is_active' is an invalid keyword argument for this function
I have tried adding the is_active field, but to no avail. Also tried messing with the REQUIRED_FIELDS because the django docs say they must match the create_superuser fields. Still no luck.
Your guidance is much appreciated. Thanks! Here is the custom user model I am using:
class CustomUserManager(BaseUserManager):
def _create_user(self, email, password, is_staff, is_superuser, **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 = self.normalize_email(email)
user = self.model(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, email, password=None, **extra_fields):
return self._create_user(email, password, False, False, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
return self._create_user(email, password, True, True, **extra_fields)
class Company(models.Model):
company_name = models.CharField(max_length=200)
class CustomUser(AbstractBaseUser):
your_name = models.CharField(max_length=254, blank=True)
company = models.ForeignKey(Company)
email = models.EmailField(blank=True, unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['your_name',]
objects = CustomUserManager()
UPDATED Omitted is_active = True from user = self.model. New error is: *TypeError: 'is_superuser' is an invalid keyword argument for this function*
I ran into the exact same error, following Mike Hibbert's excellent advanced tutorial on defining a Custom User: http://www.mikesdjangotutorials.co.uk/ I was able to get it working by adding those fields to my CustomUser:
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
...I would have assumed they were inherited from AbstractBaseUser, but sure enough, they explain this clearly enough in the docs: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-users-and-django-contrib-admin Note there are a few additional steps described there if you want your CustomUser to work in your Django Admin as well (starting with registering it, etc.)
You should remove every param that you not use in your model (CustomUser) init method and base classes init methods from that call:
user = self.model(email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
You have derived CustomUser from AbstractBaseUser that not have init and derived from models.Model. That mean that you can pass to init only names of the fields you’ve defined on your model:
user = self.model(email=email, your_name=something, company=something)
Try to derive CustomUser from AbstractUser

Categories

Resources