I am working on my Django project, I am getting this error but i don't really know how to fix it exactly, i have created my custom user model and the user manager
class AccountManager(BaseManager):
def create_user(self, email, fullname=None, birthday=None,zipcode=None, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(Email_Address=self.normalize_email(email),
name=self.normalize_email(email),
Date_of_Birth=birthday,
zipcode=zipcode
)
user.set_password(password)
user.save(using='self._db')
return user
def create_superuser(self, Email_Address, username, password):
user=self.create_user(Email_Address=self.normalize_email(Email_Address), password=password,)
user.is_admin = True
user.is_active = True
user.is_staff = True
user.is_superuser = True
user.save(using='self._db')
class User(AbstractUser):
Email_Address = models.EmailField(verbose_name='email', unique=True, blank=True, null=True)
Date_of_Birth = models.CharField(max_length=30, blank=True, null=True, default=None)
name = models.CharField(max_length=30, blank=True, null=True)
username= models.CharField(max_length=30,unique=True, blank=True, null=True)
zipcode = models.CharField(max_length=30, blank=True, 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_Address'
objects = AccountManager()
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.username
because i am using rest_framework_simplejwt for authentication i am getting this error when i try to log in
user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
rest_framework.request.WrappedAttributeError: 'AccountManager' object has no attribute 'get'
can anyone please help me with this
According to this section, https://docs.djangoproject.com/en/4.0/topics/auth/customizing/#writing-a-manager-for-a-custom-user-model, you need to extend your custom user manager from BaseUserManager.
In your code you extended from the BaseManager.
Related
I have a custom User model that inherits from AbstractBaseUser which defines the username_field = email so that users will login using emails.
class User(AbstractBaseUser):
email = models.EmailField(verbose_name="Email", unique=True)
username = models.CharField(max_length=100, unique=True)
last_name = models.CharField(max_length=100, blank=True, null=True)
first_name = models.CharField(max_length=100, blank=True, null=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_site_administrator = models.BooleanField(default=False)
is_developer = models.BooleanField(default=False)
is_project_manager = models.BooleanField(default=False)
last_login = models.DateTimeField(verbose_name="Last Login", auto_now=True)
create_on = models.DateTimeField(verbose_name="Date Created", default=timezone.now)
# So that we will be working primarily with email and not username
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
objects = UserManager()
As the objects = UserManager() and this one contains a get_by_natural_key method as follows:
def get_by_natural_key(self, username):
return self.get(username=username)
Now rather using the email to login it uses the username to login. Note that the userManager inherits from BaseUserManager like this class UserManager(BaseUserManager):
Can somebody explain to me what is going on here.
Is the problem coming from the inheritance or the get_by_natural_key() itself ?
admin dashboard:
In addition to the admin part, the template is displayed in the same way.
Ever since I customized the accounts section, in all the sections where I have used the username, there is a problem that the usernames are displayed without that name and only by displaying the phrase username.
settings.py:
AUTH_USER_MODEL = 'accounts.CustomUser'
models.py(accounts):
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError("Users must have an email address.")
if not username:
raise ValueError("Users must have a username.")
user = self.model(
email=self.normalize_email(email),
username=username
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
def get_profile_image_filepath(self, filepath):
return f'images/accounts/profiles/{self.pk}/{"profile.png"}'
class CustomUser(AbstractBaseUser, PermissionsMixin):
class Meta:
permissions = [
('all', 'all of the permissions')
]
first_name = models.CharField(max_length=30, null=True, blank=True)
last_name = models.CharField(max_length=30, null=True, blank=True)
email = models.EmailField(verbose_name='email', max_length=100, unique=True)
username = models.CharField(max_length=55, 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)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
profile_image = models.ImageField(null=True, blank=True, upload_to=get_profile_image_filepath, default='images/accounts/profiles/default_image.jpg')
objects = MyAccountManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def __str__(self):
return self.USERNAME_FIELD
def get_profile_image_filename(self):
return str(self.profile_image)[str(self.profile_image).index(f'images/accounts/profiles/{self.pk}/'):]
def get_absolute_url(self):
return reverse("accounts:user_view", args=[str(self.id)])
models.py(news):
class News(models.Model):
class Meta:
permissions = [
('all', 'all of the permissions')
]
ordering = ['-date']
title = models.CharField(max_length=255)
header_image = models.ImageField(null=True, blank=True, upload_to="images/news/header/")
body = RichTextUploadingField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
category = models.ManyToManyField(Category, default='cryptocurrency', related_name='category')
like_news = models.ManyToManyField(AUTH_USER_MODEL, blank=True, related_name='the_news')
unlike_news = models.ManyToManyField(AUTH_USER_MODEL, blank=True, related_name='the_news_unlike')
def total_likes(self):
return self.like_news.count()
def total_unlikes(self):
return self.unlike_news.count()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("news_detail", args=[str(self.id)])
Which part of the code is wrong that shows the username like this?
You need to return self.username, not self.USERNAME_FIELD:
class CustomUser(AbstractBaseUser, PermissionsMixin):
# …
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
or if you want to return the attribute with the USERNAME_FIELD, you can use the getattr(…) function [Python-doc]:
class CustomUser(AbstractBaseUser, PermissionsMixin):
# …
USERNAME_FIELD = 'username'
def __str__(self):
return getattr(self, self.USERNAME_FIELD)
Not using Djnago Default user model. Have created a Custom user model named CustomUser
class CustomUser(AbstractBaseUser):
GENDER_CHOICE = (
('MALE', 'MALE'),
('FEMALE', 'FEMALE'),
)
BLOOD_GROUP_CHOICE = (
('A+', 'A+'),
('B+', 'B+'),
('O+', 'O+'),
('AB+', 'AB+'),
('A-', 'A-'),
('B-', 'B-'),
('O-', 'O-'),
('AB-', 'AB-'),
)
RELIGION_CHOICE = (
('ISLAM', 'ISLAM'),
('HINDU', 'HINDU'),
('CHRISTIANITY', 'CHRISTIANITY'),
('OTHER', 'OTHER'),
)
email = models.EmailField(max_length=60, unique=True, verbose_name='Email')
first_name = models.CharField(max_length=30, verbose_name='First Name')
last_name = models.CharField(max_length=30, verbose_name='Last Name')
gender = models.CharField(_("Employee Gender"),
max_length=6, choices=GENDER_CHOICE, null=True, blank=True)
blood_group = models.CharField(
_("Employee Blood Group"), max_length=3, choices=BLOOD_GROUP_CHOICE, null=True, blank=True)
birth_of_date = models.DateField(
_("Employee Birth Date"), auto_now=False, auto_now_add=False, null=True, blank=True)
#address = models.CharField(_("Employee Address"), max_length=500, null=True, blank=True)
address = models.CharField(_("Employee Address"), max_length=500, null=True, blank=True)
phone_number = PhoneNumberField(null=True, blank=True)
profile_pic = models.ImageField(_("Employee Profile Picture"), upload_to='profile_pic',
height_field=None, width_field=None, max_length=None, null=True, blank=True)
religion = models.CharField(
_("Employee Religion"), max_length=15, choices=RELIGION_CHOICE, null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ('first_name', 'last_name')
objects = CustomUserManager()
def __str__(self):
return self.email
def get_short_name(self):
return self.first_name
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
class Meta:
verbose_name_plural = "Shunno ek Users"
Here is my CumstomUser models' CustomUsermanager
class CustomUserManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
if not email:
raise ValueError('You must have an email')
email = email.lower()
first_name = first_name.title()
last_name = last_name.title()
user = self.model(
email = self.normalize_email(email),
first_name = first_name,
last_name = last_name
)
#user.password = password
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, first_name, last_name, password=None):
user = self.create_user(
email = email,
first_name = first_name,
last_name = last_name,
password = password
)
user.is_admin = True
user.is_staff = True
user.save(using=self._db)
return user
This is a model of saving users Quiz answers.
class UserAns(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='quiz_user')
quizcat = models.ForeignKey(Category, on_delete=models.CASCADE)
totalq = models.DecimalField(max_digits=5,decimal_places=2)
correcta = models.DecimalField(max_digits=5,decimal_places=2)
def __str__(self):
return self.User.first_name
It is view part where i want to save the data of user answer.
def quizpage(request, slug):
if request.method == 'POST':
# totalquestion
solve = 0
for question in range(1,cat.totalq+1):
entered_answer_questionpk = request.POST.get(str(question))
ans = entered_answer_questionpk[:1]
qpk = int(entered_answer_questionpk[1:])
actualans = Question.objects.get(pk=qpk).correct_answer
if ans == actualans:
solve = solve + 1
# print(user)
usersans = UserAns(totalq=cat.totalq, correcta=solve)
usersans.quizcat = cat
print(request.user)
usersans.user = request.user
usersans.save()
return render(request, 'quiz/quizpage.html',{'questions': questions })
after saving this value in the database, when I click the table name it gives this error:
Django Version: 3.1.3
Exception Type: AttributeError
Exception Value:
'UserAns' object has no attribute 'User'
I can't understand where is my problem.
Your string method is referencing self.User and not self.user.
def __str__(self):
return self.user.first_name
Previous answer:
You should also look through your view that's rendering the page and protect any parts that access userans.user via if hasattr(userans, 'user'): or if userans.user_id:.
Another thing you can do is clean up your data. Your post view looks to be about right. But that page is failing because you have instances that still have the user property with a value of None.Open up a shell manage.py shell, import your UserAns model and see if you have any instances without a user. If you do, determine which user(s) they should map to or delete them.
UserAns.objects.filter(user__isnull=True)
I am using AbstractBaseUser for that i have created a managers.py for creating superuser.
Everything is working except these line in managers.py. Even i tried to print(user.id) before user.save(using=self._db) it is printing None
user.save(using=self._db)
user.created_by_id = user.id
user.updated_by_id = user.id
user.save()
I have also used commit=False in user.save(using=self._db, commit=False) still it is giving error. See the errors at bottom.
In my models.py i have tweo field created_by & updated_by which should should not be null. Thats why i am saving in Managers.py which is creating all this error.
How can i solve this issue. Is there better approach. This condition is only required for creating superuser.
Models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
is_active = models.BooleanField(_('is user active'), default=True)
profile_image = models.ImageField(default='user-avatar.png', upload_to='users/', null=True, blank=True)
is_staff = models.BooleanField(_('staff'), default=True)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=30, blank=True, null=True)
address = models.CharField(max_length=100, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, related_name='user_created_by')
created_on = models.DateTimeField(_('user created on'), auto_now_add=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, related_name='user_updated_by')
updated_on = models.DateTimeField(_('user updated on'), auto_now=True)
Managers.py
class UserManager(BaseUserManager):
use_in_migrations = True
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.role_id = 1
user.first_name = "Super"
user.last_name = "Admin"
user.save(using=self._db)
user.created_by_id = user.id
user.updated_by_id = user.id
user.save()
return user
def create_user(self, email, password=None, **extra_fields):
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_superuser', 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)
Error - for commit=False
super().save(*args, **kwargs)
TypeError: save() got an unexpected keyword argument 'commit'
Error - Without Commit False
raise utils.IntegrityError(*tuple(e.args))
django.db.utils.IntegrityError: (1048, "Column 'created_by_id' cannot be null")
commit=False works for ModelForms. It does not work for model instances. As the error said in your question, there is no keyword argument named commit exists in save method.
Also, before saving the user object, it can't produce any primary key. I would recommend to make created_by null able. So that you can avoid integrity error.
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, related_name='user_created_by', null=True, default=None)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, related_name='user_updated_by', null=True, default=None)
Still, if you want to enforce this restriction, then you can do that in forms or serializer or override the save method as well in the User model.
For example:
class User(...):
...
def save(self, *args, **kwargs):
if not self.is_superuser:
if not self.created_by or not self.updated_by:
raise Exception("Add these fields") # can be custom exception
super(User, self).save(*args, **kwargs)
I've been trying to store value of one checkbox, promo_consent, sent from a form into a new column that I've just created in the DB.
Whatever I do it stores always TRUE no matter wheter the checkboxed was checked or not, or stores always FALSE no matter wheter the checkboxes was checked or not.
I have this model:
class User(AbstractBaseUser, PermissionsMixin, PagePermissionMixin):
"""User model for both staff and clients.
It consists of base AbstractBaseUser class and has 2 permissions mixins.
One of them is for standard django permissions and the second is
for Page object permissions.
Note:
This model is used for OAuth2 and Django authentication.
"""
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), unique=True, blank=True)
new_email = models.EmailField(_('new email'), 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)
promo_consent = models.BooleanField(
_('Promo consent'),
default=False,
help_text=_('Shows whether user has agreed to be notified about '
'news and promo sales'))
....
....
....
and this serializer:
class RegistrationSerializer(SerializerSchemaMixin, serializers.Serializer,
SerializerValidateMixin,
EmailUniquenessValidationMixin,
PasswordValidationMixin):
"""Registration serializer."""
first_name = serializers.CharField(max_length=30, default='')
last_name = serializers.CharField(max_length=30, default='')
email = serializers.EmailField(required=True)
password = serializers.CharField(max_length=100, required=True)
password2 = serializers.CharField(max_length=100, required=True)
rules = serializers.BooleanField(required=True)
promo_consent = serializers.BooleanField(required=False)
def validate_rules(self, value):
"""Checks if 'rules' is True."""
if not value:
raise serializers.ValidationError(_('Rules has to be checked'))
else:
return value
def promo_consent(self, value):
return true
def validate(self, data):
"""Override serializer.validate()."""
self.validate_passwords_uniformity(data)
return data
def save(self, **kwargs):
"""Register new user and send confirmation email."""
language = kwargs['language']
email = self.validated_data['email']
promo_consent = self.promo_consent
self.instance = User(first_name=self.validated_data['first_name'],
last_name=self.validated_data['last_name'],
email=email,
is_active=False,
email_confirmation=uuid.uuid4().hex)
self.instance.set_password(self.validated_data['password'])
self.instance.save()
self.instance.send_email_confirmation(language, email)
return self.instance
I've been working this the second day. What am I missing here?