I am trying to add a ForeignKey between my User(AbstractBaseUser)-model and the built in Group-model. My issue now is that I cannot create a superuser, as it requires to fill the group field with 'something'.
I have created a group through the shell, called admin with id 1. However, I can't find a way to create my superuser, and set the group to admin on creation ..
Here is models.py in my /accounts app:
from django.db import models
from django.forms import ModelForm
from django.contrib.auth.models import (
BaseUserManager,
AbstractBaseUser,
Group
)
class UserManager(BaseUserManager):
def create_user(self, email, group, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email = UserManager.normalize_email(email),
password = password,
group = group
)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, group, password):
user = self.create_user(
email = UserManager.normalize_email(email),
group = group
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save()
return user
class User(AbstractBaseUser):
objects = UserManager()
date_added = models.DateField(auto_now=False, auto_now_add=True)
email = models.EmailField(unique=True, db_index=True)
group = models.ForeignKey(Group)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['group']
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_perms(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def is_staff(self):
return self.is_admin
Whenever I run migrate.py createsuperuser, it asks for email, password and Group (Group ID).
If I type admin, it gives this error:
ValueError: invalid literal for int() with base 10: 'admin'
if I type 1 (the id), it gives this error:
ValueError: Cannot assign "'1'": "User.group" must be a "Group" instance.
Meet the same problem.
Actually, group is PermissionsMixin's attribution, so what you need to do is implement PermissionsMixin and AbstractBaseUser
class User(AbstractBaseUser, PermissionsMixin):
You could change
group = group
to
group = Group.objects.get(id=group)
Within your create_superuser def.
Then you can just use the group id (which is 1 in your case) which the superuser wizard expects.
In case you'll end up working with multiple instances, I would look into creating that group in a migration instead of through the shell (so it will automatically be there when you set up a new instance and run migrations).
Related
I have the Role model. Account model take the reference from Role model using ManytoMany Field. But, I don't want to use manytomany field. It's necessary to not use ManyToMany field. Is anyone can suggest something better.
I don't want to use use ManyToMany field because, since many to many are a Django feature and not database
The given below model works fine with ManyToMany Field, I want the same with it.
from django.db import models
from django.db.models.fields import proxy
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
from django.utils.translation import gettext_lazy as _
from django.core.validators import RegexValidator
import uuid
from django.utils import timezone
import math
from django.core.validators import MinValueValidator, MaxValueValidator
ADMIN = 0
CUSTOMER = 1
SELLER = 2
DELIVERY_PARTNER = 4
class Role(models.Model):
'''
The Role entries are managed by the system,
automatically created via a Django data migration.
'''
ROLE_CHOICES = (
(ADMIN, 'admin'),
(CUSTOMER, 'customer'),
(SELLER, 'seller'),
(DELIVERY_PARTNER, 'delivery'),
)
id = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, primary_key=True)
def __str__(self):
return self.get_id_display()
class UserManager(BaseUserManager):
'''
creating a manager for a custom user model
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-a-manager-for-a-custom-user-model
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#a-full-example
'''
def create_user(self, mobile_number, password=None):
"""
Create and return a `User` with an email, username and password.
"""
if not mobile_number:
raise ValueError('Users Must Have an email address')
user = self.model(
mobile_number=self.normalize_email(mobile_number)
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, mobile_number, password):
"""
Create and return a `User` with superuser (admin) permissions.
"""
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(mobile_number, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class Account(AbstractBaseUser):
'''Account Model to store mobile number and authentication'''
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.EmailField(
verbose_name='email address',
max_length=255,
null = True,
)
type = models.ManyToManyField(Role,default=[1])
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
mobile_number = models.CharField(validators=[phone_regex], max_length=17, blank=False,null = False, unique=True)
otp = models.CharField(max_length=6, null = True, unique=True)
user_registered_on = models.DateTimeField(default=timezone.now, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = 'mobile_number'
REQUIRED_FIELDS = []
# Tells Django that the UserManager class defined above should manage
# objects of this type.
objects = UserManager()
def get_full_name(self):
pass
def get_short_name(self):
pass
# #property
# def is_superuser(self):
# return self.is_superuser
#property
def is_staff(self):
return self.is_superuser
def has_perm(self, perm, obj=None):
return self.is_superuser
def has_module_perms(self, app_label):
return self.is_superuser
#is_staff.setter
def is_staff(self, value):
self._is_staff = value
def __int__(self):
return self.mobile_number
def verify_user_type(self,type):
for x in self.type.all():
if x.id == type:
return True
return False
class Meta:
'''
to set table name in database
'''
db_table = "login"
I don't want to use use ManyToManyField because, since many to many are a Django feature and not database
There is nothing special about a ManyToManyField. Behind the curtains it creates a model (named appname_modename_m2mfieldname) with two ForeignKeys: one to the "source model" and one to the "target model". This is a pattern known as a junction table [wiki], which is how many-to-many relations are normally defined in a relational database.
You can even work with the "hidden" model with Account.type.through, which will return a reference to a model class.
While you can define an extra model for the junction table yourself, it makes no sense, and will only make the ORM more complicated. For more information, see the database representation section on the ManyToManyField [Django-doc].
I created a AbstractUser model in Django which adds some custom fields, but now whenever I create a user (whether by calling User.create_user() or with python manage.py createsuperuser), the user is created fine with a hashed password, but I cannot use the password to login. When I try to login on the admin console, I get "Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive." I cannot for the life of me figure out what is going wrong since in my database, the correct username + a hashed password appear when I create a user.
This is my user Model
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
class AccountManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
user = self.model(username=username)
user.set_password(password)
user.num_ratings_received=num_ratings_received
user.num_recipes_created=num_recipes_created
user.avg_recipe_rating=avg_recipe_rating
user.save(using=self._db)
return user
def create_user(self,username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
return self._create_user(username, password, avg_recipe_rating, num_ratings_received, num_recipes_created)
def create_superuser(self,username, password, avg_recipe_rating=None, num_ratings_received=0, num_recipes_created=0):
return self._create_user(username, password, avg_recipe_rating, num_ratings_received, num_recipes_created)
class User(AbstractUser):
user_id = models.AutoField(primary_key=True)
avg_recipe_rating = models.FloatField(blank=True, null=True)
num_ratings_received = models.IntegerField(null=False)
num_recipes_created = models.IntegerField()
last_login = None
groups = None
user_permissions = None
first_name = None
last_name = None
email = None
date_joined = None
objects = AccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
#property
def is_staff(self):
return True
#property
def is_active(self):
return True
#property
def is_superuser(self):
return True
class Meta:
managed = True
db_table = 'SampleUser'
I am fairly new at using Django, so pardon if anything in unclear.
Basically, I have created a custom user model:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class AccountManager(BaseUserManager):
def create_user(self, username, password=None):
if not username:
raise ValueError('A username is required for you to sign up')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password):
user = self.create_user(
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
username = models.CharField(max_length=40, unique=True)
password = models.CharField(max_length=999)
points = 0
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)
USERNAME_FIELD = 'username' # Cannot be included in required fields
REQUIRED_FIELDS = ['password']
objects = AccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
#staticmethod
def has_module_perms(app_label):
return True
Under class Account(AbstractBaseUser), I have defined an attribute points. I want to make it such that whenever the user redirects, the user gets some points.
from django.shortcuts import render, redirect
def home_page_view(request):
return render(request, "home_page.html", {})
def free_points(request):
request.user.points += 10
request.user.save()
return render(request, "add_points_test.html", {})
To check whether the points has been added, I changed the code under views a little:
from django.shortcuts import render, redirect
def home_page_view(request):
print(request.user.points)
return render(request, "home_page.html", {})
def add_points_view(request):
request.user.points += 10
request.user.save()
print(request.user.points)
return render(request, "add_points_test.html", {})
From what I have seen, when the user is redirected to add_points_view, the print statement under add_points_view printed out 10. However, when the user is redirected back to home_page_view, the print statement under home_page_view printed out 0 instead of 10. This shows me that points hasn't changed at all.
I'm not sure what I'm supposed to do. Sorry if this question is a bad question, I really can't find anything on the internet.
Thanks in advance.
The core problem is that you didn't define points as a persistent field, so even if you call the save method in add_points_view the information is gonna be lost.
Check https://docs.djangoproject.com/en/3.0/topics/db/models/
i just tried to create my own custom Django user model but it fails if i try to create a new user through the frontend:
Request Method: POST Request URL: http://127.0.0.1:8000/signup/ Django
Version: 2.1b1 Exception Type: AttributeError Exception Value:
'Manager' object has no attribute 'get_by_natural_key'
First i created a new Django App "accounts"
then i've added the following to models.py of the accounts app:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
#User Model Manager
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not username:
raise ValueError('Error: The User you want to create must have an username, try again')
user = self.model(
user=self.normalize_username(username),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, username, password):
"""
Creates and saves a staff user with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, username, password):
"""
Creates and saves a superuser with the given username and password.
"""
user = self.create_user(
username,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
def get_full_name(self):
# The user is identified by their Username address
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self): # __unicode__ on Python 2
return self.user
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
model.py of my actual blog app:
from django.db import models
from django.utils import timezone
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor
# Categorys of Post Model
class Category(models.Model):
title = models.CharField(max_length=255, verbose_name="Title")
description = models.TextField(max_length=1000, null=True, blank=True)
cover = fields.ImageField(upload_to='categorycovers/', blank=True, null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 350, 'max_height': 350}))
])
icon = fields.ImageField(upload_to='categoryicons/', blank=True, null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 16, 'max_height': 16}))
])
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
ordering = ['title']
def __str__(self):
return self.title
#Post Model
class Post(models.Model):
author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
title = models.CharField(max_length=75)
content = models.TextField(max_length=10000)
tag = models.CharField(max_length=50, blank=True)
category = models.ForeignKey(Category, verbose_name="Category", on_delete=models.CASCADE, null=True)
postattachment = fields.FileField(upload_to='postattachment/%Y/%m/%d/', blank=True ,null=True)
postcover = fields.ImageField(upload_to='postcover/%Y/%m/%d/', null=True, dependencies=[
FileDependency(processor=ImageProcessor(
format='JPEG', scale={'max_width': 200, 'max_height': 200}))
])
created_date = models.DateField(auto_now_add=True)
published_date = models.DateField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
class Meta:
ordering = ["-title"]
def __str__(self):
return self.title
#Comment(s) of Post Model
class Comment(models.Model):
author = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
post=models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
created_date = models.DateField(default=timezone.now)
published_date = models.DateField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.text
After that i jumpt back to settings.py and added the custom user model to my acctual blog application:
AUTH_USER_MODEL = 'accounts.User'
and i also added
INSTALLED_APPS = [
...
'accounts',
...
]
I dont want any email address for my users. i simply and only want them to be authenticated through the username...
Any hints? Thanks :)
Django AbstractBaseUser class has no field username
in your declaration you declare a username field and named it user
but USERNAME_FIELD is username
change your model like this
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
...
also you can rename user field in User model to username and problem solved.
In error django.core.exceptions.FieldError: Unknown field(s) (username) specified for User, Django complained about unknown field username in your Custom User model, you don't have username field but you stated USERNAME_FIELD = 'username'.
The simple solution is to rename your user field to username.
If you need that name for some reason (user) you should change username to user in get_full_name and get_short_name and don't forget also in create_user (user = self.model(user =self.normalize_username(username),))
Try:
Reaname all created users to some other name (ex. my_user) because you have tow varibales with the same name (the USERNAME_FIELD and the user created)
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
#User Model Manager
class UserManager(BaseUserManager):
def create_user(self, user, password=None):
"""
Creates and saves a User with the given username and password.
"""
if not user:
raise ValueError('Error: The User you want to create must have an username, try again')
my_user = self.model(
user=self.normalize_username(user),
)
my_user.set_password(password)
my_user.save(using=self._db)
return my_user
def create_staffuser(self, user, password):
"""
Creates and saves a staff user with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.save(using=self._db)
return my_user
def create_superuser(self, user, password):
"""
Creates and saves a superuser with the given username and password.
"""
my_user = self.create_user(
user,
password=password,
)
my_user.staff = True
my_user.admin = True
my_user.save(using=self._db)
return my_user
class User(AbstractBaseUser):
user = models.CharField(
verbose_name='username',
max_length=30,
unique=True,
)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'user'
REQUIRED_FIELDS = [] # Username & Password are required by default.
def get_full_name(self):
# The user is identified by their Username address
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self): # __unicode__ on Python 2
return self.user
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
Your settings.py file looks great.
I hope this will help.
I'm trying to create custom authentication in Django where the identifier is an email, there is a required field called name and a password field. While creating the superuser, i'm getting an error.
TypeError: create_user() got multiple values for keyword argument 'name'
Here is my models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, name, email, password=None):
"""
Creates and saves a User with the given email, name and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
name=name,
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
"""
Creates and saves a superuser with the given email, name and password.
"""
user = self.create_user(email,
password=password,
name=name
)
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
name = models.CharField(max_length=20)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
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
# On Python 3: def __str__(self):
def __unicode__(self):
return self.name
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
class MyUser(AbstractBaseUser):
name = models.CharField(max_length=20)
email = models.CharField(max_length=40, unique=True)
REQUIRED_FIELDS = ['name']
USERNAME_FIELD = 'email'
Here is the traceback
File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/management/commands/createsuperuser.py", line 141, in handle
self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
File "/home/jaskaran/coding/django/TaskMan/taskmanager/models.py", line 32, in create_superuser
name=name
TypeError: create_user() got multiple values for keyword argument 'name'
Change your function call
user = self.create_user(email,
password=password,
name=name
)
to
user = self.create_user(email=email, # use email=email
password=password,
name=name
)
The order of your parameters is not correct. The email is passed before name and then again name is passed as keyword parameter.
I got the answer, and this is how you frame your code
def create_superuser(self, email, name, password):
"""
Creates and saves a superuser with the given email, name and password.
"""
user = self.create_user(
email,
name,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user