Creating a custom super user as part of a class Im taking - python

I'm currently taking a custom rest API class that is teaching me to build my own custom REST APIs for authentication, as well as creating custom user models.
Im running into a slight problem with the following code base:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager
# Create your models here.
class UserProfileManager(BaseUserManager):
""" Manager for User Profiles"""
def create_user(self, email, name, password=None):
""" Create a new user profile"""
if not email:
raise ValueError('Users must have an email address')
email = self.normalize_email(email)
user = self.model(email=email, name=name)
""" user.set_password(password) encrypts the passwords as a hash """
user.set_password(password)
""" This allows you to specify which database to use for the user accounts. Django Supports multiple Databases!!! 8D """
user.save(using=self._db)
return user
def create_superusr(self, email, name, password):
""" Create and save a new superuser with given details """
user = self.create_user(email, name, password)
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class UserProfile(AbstractBaseUser, PermissionsMixin):
""" Database model for users in system """
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 = UserProfileManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def get_full_name(self):
""" Retrieve Full Name of User"""
return self.name
def get_short_name(self):
""" Retrieve short name of User"""
return self.name
def __str__(self):
"""Return String representation of our User """
return self.email
The primary issue is in the UserProfileManager section, the issue according to the error output is with the create_superuser section.
The error message is the following:
AttributeError: 'UserProfileManager' object has no attribute 'create_superuser'
I've checked to ensure that in my settings.py file to ensure that using the custom model, as well as Ive checked to confirm that the makemigrations and migrations commands have been run. Ive also tested by deleting the init files, as well as the database and rebuilding them.
Ive also tested to ensure that superuser works, and django admin portal is enabled, all of which without the custom user profile works fine, but with it it breaks, so I know my issue should have something to do with the section of code above, but I cant find anything. Ive checked with the official django docs, but Im at a loss at this point.

I found my error. E for Error, as in the e that was missing in def create_superusEr.
Im good now! This site is awesome! Sometimes just asking the question helps to answer it.

Related

Group and Permissions Assignment Missing when using Custom User Model

I am building an app with multiple roles defined through Django Groups.
I started with a custom user model, defined as below.
I am seeing a weird difference in the groups and permissions use when using a custom user model, like the inheritance is missing something.
I would like to use a custom user model so I don't use username but I also need multiple groups and permissions in my application.
from django.db import models
from django.contrib.auth.models import AbstractUser, AbstractBaseUser, BaseUserManager, PermissionsMixin
import random
import string
from slugify import slugify
# Create your models here.
class MyAccountManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError("You 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),
)
user.set_password(password)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
#custom user account model
class User_Account(AbstractUser):
email = models.EmailField(verbose_name='email', max_length=60, 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)
username = models.CharField(max_length=100, null=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)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = MyAccountManager()
def __str__(self):
return self.email
When I create a new group with the custom user model, the group gets automatically assigned to all created users. I reproduced this behavior both programmatically and through the Django Admin.
When I use the default user model the group creation doesn't assign groups to all users automatically.
I also discovered that when using a custom user model the Django Admin for the users is not the same (the group and permission assignment fields are incomplete - screenshots below)
Weird incomplete Django Admin interface with groups and permissions missing the available fields
Normal Django Admin interface with group and permission assignment as expected - default user model
I managed to fix the issue in the Admin panel. It seems that it's a visual rendering problem caused by a wrong Admin class.
The error was caused by the following:
filter_horizontal = ()
list_filter = ()
fieldsets = ()
I have actually added the proper parameters in the class above but forgot to comment out/remove these lines. Works properly after commenting them out.
Try removing
filter_horizontal = (),
It worked for me.

Retrieving user details using username from extended User Model in Django

I'm trying to retrieve the details of a user using the username test from an extended User model in Django. But I am unable to do it. It's giving me the error:
ValueError at / invalid literal for int() with base 10: 'test'
Following is my code:
models.py
class DocchainUser(models.Model):
docchainuser_name = models.OneToOneField(User, on_delete = models.CASCADE, default='x')
address = models.CharField(max_length=64,unique=True)
def __str__(self):
return self.address
views.py
def my_users(request):
if request.method == 'POST':
username = request.POST.get('username')
user = authenticate(username=username)
if user:
if user.is_authenticated:
signBool = signatureAuth(username)
if signBool == 'AUTHENTICATED':
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])
return HttpResponseRedirect('/dashboard')
....
And the signatureAuth() now:
def signatureAuth(username):
userModel = DocchainUser.objects.filter(docchainuser_name=username)
address = userModel.address
print(address)
...
I'm retrieving the user details using username: test in signatureAuth() method. test is already present in my User as well as DocchainUser model.
You don't have an extended user model, you have a separate model with a one-to-one relation to User. So in order to query that model by username, you need to follow the relationship.
userModel = DocchainUser.objects.filter(docchainuser_name__username=username)
Note, one of the reasons you struggled here is that your OneToOneField is probably misnamed; the relationship is with the entire model, not the username; you should call it just docchainuser.
(Also note, your if user.is_authenticated is pointless; that just checks that the user is an instance of User rather than AnonymousUser, which you know it is because you just explicitly retrieved it from the User model.)

Django register extended user

I'm trying to create and manage a custom user in django.
I saw there are two possibilities, and i've chosen to extend (not create a new auth).
Models
models.py
class Artists(models.Model):
user = models.OneToOneField(User)
artist_image = models.ImageField(null=True, blank=True, upload_to="/artist_image/")
def __str__(self):
return 'Profil de {0}'.format(self.username)
def get_absolute_url(self):
return reverse('artist-details', kwargs={'pk': self.pk})
As i read in doc, I just make a OneToOne field with the User class of django auth models, so I can access method and properties, such as username, email, on my own user (here Artists).
form.py
class CreateArtistForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email')
def save(self, commit=True):
user = super(CreateArtistForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
Here I extend UserCreationForm to prepare a form a little different (I want to have email field on my register form).
But here is my question : I first tried with
class Meta:
model = Artists
fields = ('user.username', 'user.email')
But I the error fields unknown in model Artist.
So I tried just with username and email and same error.
So I changed the model = Artists to User, and it works fine.
But now how i register my Artist Object when the user is saved?
Do I have to make something like (in save()):
artist = Artists()
artist.user = user
artist.save()
Or override create_user()?
I'm quite lost here and i'm looking docs and questions not able to find something because most of example people define their own auth.
Thanks in advance
Besta
edit : i'm using django 1.8.2 and python 3.4

Django delete superuser

This may be a duplicate, but I couldn't find the question anywhere, so I'll go ahead and ask:
Is there a simple way to delete a superuser from the terminal, perhaps analogous to Django's createsuperuser command?
There's no built in command but you can easily do this from the shell:
> python manage.py shell
$ from django.contrib.auth.models import User
$ User.objects.get(username="joebloggs", is_superuser=True).delete()
In the case of a custom user model it would be:
python manage.py shell
from django.contrib.auth import get_user_model
model = get_user_model()
model.objects.get(username="superjoe", is_superuser=True).delete()
An answer for people who did not use Django's User model instead substituted a Django custom user model.
class ManagerialUser(BaseUserManager):
""" This is a manager to perform duties such as CRUD(Create, Read,
Update, Delete) """
def create_user(self, email, name, password=None):
""" This creates a admin user object """
if not email:
raise ValueError("It is mandatory to require an email!")
if not name:
raise ValueError("Please provide a name:")
email = self.normalize_email(email=email)
user = self.model(email=email, name=name)
""" This will allow us to store our password in our database
as a hash """
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
""" This creates a superuser for our Django admin interface"""
user = self.create_user(email, name, password)
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class TheUserProfile(AbstractBaseUser, PermissionsMixin):
""" This represents a admin User in the system and gives specific permissions
to this class. This class wont have staff permissions """
# We do not want any email to be the same in the database.
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)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name',]
# CLASS POINTER FOR CLASS MANAGER
objects = ManagerialUser()
def get_full_name(self):
""" This function returns a users full name """
return self.name
def get_short_name(self):
""" This will return a short name or nickname of the admin user
in the system. """
return self.name
def __str__(self):
""" A dunder string method so we can see a email and or
name in the database """
return self.name + ' ' + self.email
Now to delete a registered SUPERUSER in our system:
python3 manage.py shell
>>>(InteractiveConsole)
>>>from yourapp.models import TheUserProfile
>>>TheUserProfile.objects.all(email="The email you are looking for", is_superuser=True).delete()
No need to delete superuser...just create another superuser... You can create another superuser with same name as the previous one.
I have forgotten the password of the superuser so I create another superuser with the same name as previously.
Here's a simple custom management command, to add in myapp/management/commands/deletesuperuser.py:
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.core.management.base import CommandError
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('username', type=str)
def handle(self, *args, **options):
try:
user = User.objects.get(username=options['username'], is_superuser=True)
except User.DoesNotExist:
raise CommandError("There is no superuser named {}".format(options['username']))
self.stdout.write("-------------------")
self.stdout.write("Deleting superuser {}".format(options.get('username')))
user.delete()
self.stdout.write("Done.")
https://docs.djangoproject.com/en/2.0/howto/custom-management-commands/#accepting-optional-arguments
A variation from #Timmy O'Mahony answer is to use the shell_plus (from django_extensions) to identify your User model automatically.
python manage.py shell_plus
User.objects.get(
username="joebloggs",
is_superuser=True
).delete()
If the user email is unique, you can delete the user by email too.
User.objects.get(
email="joebloggs#email.com",
is_superuser=True
).delete()
There is no way to delete it from the Terminal (unfortunately), but you can delete it directly. Just log into the admin page, click on the user you want to delete, scroll down to the bottom and press delete.

Why is this Django form bypassing my custom manager when creating a new object?

I have a basic Django ModelForm to create a new user:
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
# stuff here
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
if commit:
user.save()
return user
I also have a custom UserManager for handling the User creation function, which also creates a UserProfile and attaches it to the User:
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
"""Create a standard user."""
email = self.normalize_email(email)
user = self.model(email=email)
user.set_password(password)
user.save()
profile = UserProfile()
profile.user = user
profile.save()
return user
class User(AbstractBaseUser, PermissionsMixin):
objects = UserManager()
However, whenever the UserCreationForm is called successfully, it creates the User, but doesn't create the UserProfile.
My question is, why is the UserCreationForm bypassing my custom UserManager? Is there some special syntax I need to give the form to tell it my model has a custom manager?
I am also using django.views.generic.CreateView as the view, so I guess I could change the post method manually to create a User and UserProfile, but I'd like to know why this is failing before coming up with some hacky fix considering it seems like a very basic operation.
Thanks

Categories