Django user registration with phone and password - django

i am creating custom user model in django using abstract base user class, i want to create user with only two fields "phone and password " and name being the optional field , which i have set in my models .py that blank =true. i have created a rest api for user registration using my custom user model, but every time i try to create new user with phone and password it gives me below error:-
IntegrityError at /api/users/
UNIQUE constraint failed: accounts_user.name
Request Method: POST
Request URL: http://127.0.0.1:8000/api/users/
Django Version: 3.0.1
Exception Type: IntegrityError
Exception Value:
UNIQUE constraint failed: accounts_user.name
Exception Location: /usr/local/lib/python3.7/site-packages/django/db/backends/sqlite3/base.py in execute, line 396
Python Executable: /usr/local/opt/python/bin/python3.7
Python Version: 3.7.6
Python Path:
['/Users/raghav/milkbasketdemo/milkbasketdemo',
'/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
'/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
'/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
'/usr/local/lib/python3.7/site-packages']
Please help where i am going wrong , i have searched and tried changing code number of times but nothing is working for me.
please find the below code of models.py
class UserManager(BaseUserManager):
def create_user(self,phone, password=None,is_staff=False,is_admin=False,is_active=True):
if phone is None:
raise TypeError('Users must have a phonenumber.')
user = self.model(phone=phone)
user.set_password(password)
user.staff=is_staff
user.admin=is_admin
user.active=is_active
user.save(using=self._db)
return user
def create_staffuser(self, phone, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
phone,
password=password,
is_staff=True
)
# user.staff = True
user.save(using=self._db)
return users
def create_superuser(self, phone, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
phone=phone,
password=password,
is_staff=True,
is_admin=True
)
#user.staff = True
#user.admin = True
#user.active=True
user.save(using=self._db)
return user
class User(AbstractBaseUser,PermissionsMixin):
phone_regex=RegexValidator(regex = r'^[6-9]\d{9}$',message='please enter the correct phonenumber')
#name_regex=RegexValidator(regex=r'/^[A-Za-z]+$/',message='Please enter the correct name')
phone=models.CharField(validators=[phone_regex],max_length=15,unique=True)
name=models.CharField(max_length=15,unique=True,blank=True)
date_joined=models.DateTimeField(verbose_name='date joined',auto_now_add=True)
last_login=models.DateTimeField(verbose_name='last login',auto_now=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False)
first_login=models.BooleanField(default=False)
USERNAME_FIELD='phone'
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
return self.phone
#property
def token(self):
return self._generate_jwt_token()
def get_full_name(self):
return self.name
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
Below is code of serializer.py
class RegistrationSerializer(serializers.ModelSerializer):
password = serializers.CharField(
max_length=128,
min_length=8,
write_only=True
)
token = serializers.CharField(max_length=255, read_only=True)
class Meta:
fields = ['phone', 'password']
def create(self, validated_data):
return User.objects.create_user(**validated_data)

Related

I am trying to get UserProfile using Django Simple JWT, however I get error "Invalid data. Expected a dictionary, but got User."

I wanted to use email instead of username to login the user, so I obtained below code from the django documentation from custom authorization section.
class UserManager(BaseUserManager):
def create_user(self, email, name, password=None, password2=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('User must have an Email Address')
user = self.model(
email=self.normalize_email(email),
name = name
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password=None):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
name=name,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
name = models.CharField(max_length=255)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return self.is_admin
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
I have used custom user manager and added email field and name field. Name is required and authorization will be done using email of the user. I was able to create super user and login successfully. I was also able to register the user using REST endpoint. I want to try to login the user and view the profile. I was able to successfully login user and get access & refresh token using Simple JWT. But when I try to hit profile endipoint I get
"Invalid data. Expected a dictionary, but got User."
Error
My view is as follows, I am using UserRenderer to get response in the required format, this works correctly for user registration and login endpoints and I dont think thats the issue here.:
#api_view(["GET"])
#renderer_classes([UserRenderer])
#permission_classes([IsAuthenticated])
def user_profile(request):
print("DATA", request.user)
serializer = UserProfileSerializer(data=request.user)
if serializer.is_valid():
return Response({"data":serializer.data}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Here print statement give me the email of the user trying to access the endpoint, I think it obtains it from the token passed.
And serializer I used is
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email']
I am passing access token as Bearer token in header section of the endpoint
You are passing request.user inside serializer data, you should do:
serializer = UserProfileSerializer(data=request.data)

I am creating a backend for eber website but in got his error

I am creating a backend for eber website but got an error
This is the code:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
# Create your models here.
class CustomUserManager(BaseUserManager):
def create_user(self, email, password = None, **kwargs):
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= None):
user = self.create_user(
email,
password = password,
)
user.is_admin = True
user.is_staff = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name = 'email address',
max_length = 255,
unique = True,
)
is_admin = models.BooleanField(default = False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
objects = CustomUserManager()
#USERNAME_FIELD = 'email'
def __str__(self):
return self.email
def has_perm(self, perm, obj= None):
"Does the user have a specific permission?"
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app?"
return True
The error I got is this:
TypeError at /api/v1/users/
create_user() missing 1 required positional argument: 'username'
Request Method: POST
Request URL: http://127.0.0.1:8000/api/v1/users/
Django Version: 3.1.5
Exception Type: TypeError
Exception Value:
create_user() missing 1 required positional argument: 'username'
Exception Location: /home/danish-khan/django_drf/eberbackend/apps/users/views.py, line 14, in create
Python Executable: /home/danish-khan/django_drf/django/bin/python
Python Version: 3.8.5
Python Path:
['/home/danish-khan/django_drf/eberbackend',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/home/danish-khan/django_drf/django/lib/python3.8/site-packages']
Server time: Tue, 23 Feb 2021 03:58:00 +0000
I have tried very much but can't fix this.
I am trying to create a user, superuser only by email as username.
I mean username is not required so this error occurs and can't be fixed.
I email will be used instead of username.
I want to fix this issue in simple easy code.
I faced the same problem once.
You just have to add this in your settings.py file and everything will work just fine.
AUTH_USER_MODEL = 'your_app.Users'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
In your code, you are missing `username.
user = self.create_user(
email,
password = password,
)
you can update it like:
user = self.create_user(
username=username
email,
password = password,
)
And similarly, you need to update in create_user method.
Also from the docs explicitly states the UserManager class assumes that you have both username and email fields. Since you don't, you would need to create your own subclass that defines the create_user method but doesn't expect a username parameter.

customising django user model is failing

**Hi
I am trying to customize the django default user. Applying migrations works fine. However I get an error when i try to create a super user. Can you please advise why I get this error?
******************** self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
File "/home/gravityns/PycharmProjects/dev/shop/models.py", line 54, in create_superuser
user.is_staff = True
AttributeError: can't set attribute
# accounts.models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
from django.core.validators import RegexValidator
class UserManager(BaseUserManager):
def create_user(self, username, password, email):
"""
Creates and saves a User with the given email and password.
"""
if not username:
raise ValueError('Users must have a username')
if not email:
raise ValueError('Users must have an email address')
user = self.model(
username = username,
email = self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, username, password, email):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
username,
email,
password,
)
user.is_staff = True
user.save(using=self._db)
return user
def create_superuser(self, username, password, email):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
username,
email,
password
)
user.is_staff = True
user.is_admin = True
user.save(using=self._db)
return user
USERNAME_REGEX = '^[a-zA-Z0-9.#+-]*$'
class User(AbstractBaseUser):
username = models.CharField(max_length=255, validators=[
RegexValidator(regex= USERNAME_REGEX,
message = 'Username must be Alphanumeric or any of the following: ". # + -"')],
unique=True
)
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
created_at = models.DateField(auto_now_add=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False) # a admin user; non super-user
# notice the absence of a "Password field", that's built in.
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email'] # Email & Password are required by default.
objects = UserManager()
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 __str__(self): # __unicode__ on Python 2
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?"
return self.is_staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.is_admin
#property
def is_active(self):
"Is the user active?"
return self.is_active
You're overwriting the normal is_staff attribute with your custom property. You need to rename those properties so that they don't clash with the stuff AbstractBaseUser already implements. Look at how that class implements is_staff and others etc here: https://github.com/django/django/blob/master/django/contrib/auth/models.py#L288
You have a field on User model as User.is_staff and a #property with the same name. So you can't set the property of the model object by user_instance.is_staff = True.
You can have is_staff as a field or as a class property, not both.
You have unncessarily defined properties for is_staff, is_active and is_superuser. But those are already fields, with the exact same name. Therefore, when you try and set user.is_staff = True, Python access your property, and tries to "set" that, rather than the field.
There is no reason to do this. The only reason you would need to define those properties is if you want to disallow setting the fields themselves. But you don't want to do that. (Alternatively, if you didn't want fields at all, but wanted to base the value on some custom logic - but, again, you wouldn't be able to set them unless you defined a custom setter.)
Remove all three of those properties.

Django: no attribute 'get_by_natural_key'

i currently try the implement my very own user model. Therefor i created a new app "accounts". But each time when i try to create anew user i get the following error:
AttributeError: 'AnonymousUser' object has no attribute '_meta'
accounts - models.py:
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 fields
user = models.CharField(verbose_name='username',max_length=30,unique=True)
bio = models.TextField(max_length=5000, blank=True, null=True)
pubpgp = models.TextField(blank=True, null=True)
#Account typs
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 ;)
return self.user
def get_short_name(self):
# The user is identified by their Username address
return self.user
def __str__(self):
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
objects = UserManager()
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',
...
]
All this user model/django stuff is a bit new to me and i have no idea what the error "AttributeError: 'Manager' object has no attribute 'get_by_natural_key'" means.
Thanks :D
Edit: AttributeError: 'UserManager' object has no attribute 'normalize_username'
normalize_username belongs to AbstractBaseUser, you can try the code below.
In signup view, when you save the form you already get the user (form.save()). Because the reason from authentication is to verify a set of credentials and getting the user (but we already have the user)
In this line: user = authenticate(username=username, password=raw_password), the authenticate method takes request as the first argument, so it should be: user = authenticate(request, username=username, password=raw_password), therefore you got the Error 'AnonymousUser' object has no attribute '_meta'.
Try:
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('post_list')
Edit UserManager:
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)
Here is the signature of create_user and create_superuser
create_user(*username_field*, password=None, **other_fields)
create_superuser(*username_field*, password, **other_fields)
They take the USERNAME_FIELD as the first argument, and yours is user
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.model.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
I hope this will help.

Django 1.5. Users profile creation

I use django 1.5 with custom model MyUser. I want to make users profile page, where he can modify only one field - 'about'.
I tried something like that:
forms.py:
class UserSettingsForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ('about')
view.py:
class UserSettings(UpdateView):
form_class = UserSettingsForm
template_name = "user/settings.html"
def get_object(self, queryset=None):
return self.request.user
def get_success_url(self):
return reverse('user_detail', args=[self.request.user.username])
urls:
url(r'^settings/$', UserSettings.as_view(), name='user_settings')
model:
class MyUserManager(BaseUserManager):
def create_user(self, email, 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, email, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(email,
password=password,
#date_of_birth=date_of_birth
)
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,
db_index=True,
)
last_name=models.CharField(max_length=30)
first_name=models.CharField(max_length=30)
about=models.TextField(blank=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['last_name','first_name','about']
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
But I got error: django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'app.MyUser' that has not been installed
How can I make users profile in django 1.5? Thx!
MyUser class should be under the application named 'app' in your settings file in order for the auth framework to pick it.