I am using jwt auth system When I fill the field it returns jwt token easily but if i want to create a profile with this token it says
CustomUser has no attribute 'objects'
my users/models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=40, unique=True)
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
date_joined = models.DateTimeField(default=timezone.now)
object = UserManager()
USERNAME_FIELD = 'email'
def save(self, *args, **kwargs):
super(CustomUser, self).save(*args, **kwargs)
return self
and user/views.py
class CreateUserAPIView(APIView):
permission_classes = (AllowAny,)
def post(self, request):
user = request.data
serializer = UserSerializer(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
try:
email = request.data['email']
password = request.data['password']
user = CustomUser.object.get(email=email, password=password)
if user:
try:
payload = jwt_payload_handler(user)
token = jwt.encode(payload, settings.SECRET_KEY)
user_details = {}
user_details['id'] = "%s" % (user.id)
user_details['token'] = token
user_logged_in.send(sender=user.__class__,
request=request, user=user)
return Response(user_details, status=status.HTTP_200_OK)
except Exception as e:
raise e
else:
return Response(status=status.HTTP_403_FORBIDDEN)
except KeyError:
res = {'error': 'please provide a email and a password'}
return Response(res)
with this code I am getting a token but with this token I cannot create a profile
profile/models.py
class Profile(TimeModel):
user = models.OneToOneField('user.CustomUser', on_delete=models.CASCADE)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=30, null=True)
birthdate = models.DateTimeField(null=True)
image = models.ImageField(upload_to='path', null=True)
def __str__(self):
return self.user.email
here what i have tried so far. I tried to look for solution but could not get any and none of them solved my problems. How can I solve this problems. Any help would be appreciated! Thank you!
P.S
In the serializers file there is no additional overridden functions it just includes model name and fields of Profile model
You're using a custom manager and you assign that to object instead of objects in your CustomUser model.
class CustomUser(AbstractBaseUser, PermissionsMixin):
...
objects = UserManager()
...
Also, your queryset should use CustomUser.objects.get(...) Another thing I've realized is you're overriding the save method inside your CustomUser but you're not doing anything specific there, so there's no need to override that method.
I think you've a typo in your code - it should be objects:
user = CustomUser.objects.get(email=email, password=password)
Related
I am trying to create a user profile, I feel i have everything correct but still it doesn't register.
You see my codebase below, please help
What i did:
Models.py:
class UserManager(BaseUserManager):
def create_user(self, username, email, name, address,roleId,customerId,dso password=None,):
if username is None:
raise TypeError('User should have a userame')
if email is None:
raise TypeError('Users should have a Email')
user = self.model(username=username , email = self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password=None):
if password is None:
raise TypeError('User should have a password')
user=self.create_user(username,email,password,)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(models.Model):
dso = models.ForeignKey(Dso,related_name='dso',default=NULL,blank=False,on_delete=models.CASCADE)
name = models.CharField(max_length=70, blank=False, default='')
email = models.EmailField(max_length=70, blank=False, default='')
password = models.CharField(max_length=70, blank=False, default='')
address = models.CharField(max_length=70, blank=False, default='')
roleId = models.IntegerField(blank=False, default='1')
isActive = models.BooleanField(blank=False, default=True)
customerId = models.CharField(max_length=70, blank=False, default='')
dateJoined = models.DateTimeField(auto_now_add=False, blank=False, default=NULL)
#property
def energy_data(self):
energydata = EnergyData.objects.filter(customerId=self.customerId).first()
return energydata
Serializers.py:
class RegisterSerializer(serializers.ModelSerializer):
password = serializers.CharField(max_length = 68, min_length=6, write_only = True)
class Meta:
model=User
fields=['email','username','password','name','address','customerId',
'dso', 'roleId']
def validate(self, attrs):
email = attrs.get('email', '')
username = attrs.get('username', '')
if not len(username) >= 4:
raise serializers.ValidationError('Username must be morethan 4 letters or characters')
return attrs
def create(self, validated_data):
return User.objects.create_user(**validated_data)
Views.py:
class RegisterView(generics.GenericAPIView):
serializer_class= RegisterSerializer
def post(self, request):
user = request.data
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
user_data = serializer.data
user= User.objects.get(email=user_data['email'])
token = RefreshToken.for_user(user).access_token
current_site = get_current_site(request).domain
relativeLink = reverse('email-verify')
absolute_url = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body= 'Hi '+ user.username + ' Use this link below to verify your email \n'+ absolute_url
data = {'email_subject': 'Verify Your Email', 'email_body': email_body , 'to_email': user.email}
Util.send_email(data)
return Response(user_data, status = status.HTTP_201_CREATED)
URL Path:
path('register/', RegisterView.as_view(), name="register" )
When i do this and try to test i get the error, '(1048, "Column 'dso_id' cannot be null")'
Please kindly help as i am new to django rest framework.
error thrown from this line in User Model
dso = models.ForeignKey(Dso,related_name='dso',default=NULL,blank=False,on_delete=models.CASCADE)
you set default NULL while don't set null and blank fields True
so change to this or remove default=NULL(None)
dso = models.ForeignKey(Dso,related_name='dso',default=NULL, blank=True, null=True, on_delete=models.CASCADE)
also you should not useNULL in python, use None replace that
I have two models staff and UserAddress and I'm trying to add the staff through models. But I get this error:
AttributeError at /accounts/signup/staff/
'NoneType' object has no attribute 'add'
What should I do now, Could some one help me?
I wanted to register a staff but this thing happened.
models.py:
class UserAddress(models.Model):
city = models.CharField(max_length=100)
address = models.CharField(max_length=200)
zip_code = models.CharField(max_length=15, blank=True)
def __str__(self):
return str(self.id)
class CustomUser(AbstractUser):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(unique=True)
user_address = models.ForeignKey(UserAddress, on_delete=models.CASCADE, null=True)
class Staff(CustomUser):
def save(self, *args, **kwargs):
if not self.id:
self.is_staff = True
self.is_superuser = False
return super(Staff, self).save(*args, **kwargs)
class Meta:
proxy = True
forms.py:
class StaffCreationForm(UserCreationForm):
first_name = forms.CharField(max_length=100, required=True)
last_name = forms.CharField(max_length=100, required=True)
email = forms.EmailField(required=True)
city = forms.CharField(max_length=100)
address = forms.CharField(max_length=100)
zip_code = forms.CharField(max_length=15, required=True)
class Meta(UserCreationForm.Meta):
model = CustomUser
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.first_name = self.cleaned_data.get("first_name")
user.last_name = self.cleaned_data.get("last_name")
user.email = self.cleaned_data.get("email")
user.is_staff = True
user.save()
address = UserAddress.objects.create(city=self.cleaned_data.get("city"),
address=self.cleaned_data.get("address"),
zip_code=self.cleaned_data.get("zip_code"))
user.user_address.add(address)
return user
views.py:
class StaffSignUpView(CreateView):
model = CustomUser
form_class = StaffCreationForm
template_name = "accounts/signup_user.html"
def get_context_data(self, **kwargs):
kwargs["user_type"] = "staff"
return super().get_context_data(**kwargs)
def form_valid(self, form):
user = form.save()
login(self.request, user)
return redirect("home")
Your user.user_address object does not contain any value that is why you're getting this error 'NoneType' object has no attribute 'add' because default it's value is None and None datatype does not contain add() method so try this
user.user_address = address
user.save() # don't forget to save user
this will assign address object to user.user_address
I am creating a login method using Django-rest-Knox. I have created a custom user in app using AbstractBaseUser.
This is my views.py
class LoginView(GenericAPIView):
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) # Load request body to serializer
serializer.is_valid(raise_exception=True) # Validate data in serializer and raise an error if one is found
user = serializer.validated_data # Get the validated data from the serializer
token = AuthToken.objects.create(user)[1] # Create an Authentication Token for the user
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data, # Get serialized User data
"token": token
})
Serializer.py
class LoginSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
# class Meta:
# model = User
# fields = ('username', 'password')
def Validate(self, data):
user = authenticate(**data)
if user:
return user
raise serializers.ValidationError("Incorrect Credentials")
This is my custom user model
class User(AbstractBaseUser):
_id = models.AutoField
email = models.EmailField(verbose_name='email', max_length=255, unique=True)
username = models.CharField(verbose_name='username', max_length = 100, unique=True)
name = models.CharField(max_length = 100)
date_joined = models.DateTimeField(verbose_name="date-joined", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="last-login", auto_now=True)
category = models.CharField(max_length=50, default= "teacher")
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_teacher = models.BooleanField(default=False)
is_parent = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
def __str__(self):
# return self.email
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
I am getting an Value error when submitting login as Cannot assign "OrderedDict([('username', 'api_test'), ('password', 'test#123')])": "AuthToken.user" must be a "User" instance.
I think somewhere Django/Knox is not able to get user and user.is_active in my LoginSerializer. I have initiated my user model from initial migrations.
Any help to resolve this issue would be great. Thanks.
In this part of your code :
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data, # Get serialized User data
"token": token
})
You need to replace the token by an instance of the user on which this token belong so for example :
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data, # Get serialized User data
"token": User.objects.get(token=token)
})
I have three types of users in CustomUser model each provided with an integer value. Also, I have made a separate view for login for vendor.
I registered a user as vendor from default django admin. But I am unable to login as a vendor when I call the login as vendor api. I get the error message saying this is not a seller account.
My models:
class CustomUser(AbstractUser):
username = None
first_name = models.CharField(max_length=255, verbose_name="First name")
last_name = models.CharField(max_length=255, verbose_name="Last name")
email = models.EmailField(unique=True)
Type_Choices = (
(1, 'Customer'),
(2, 'Vendor'),
(3, 'Admin'),
)
user_type = models.IntegerField(choices=Type_Choices, default=1)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name"]
objects = CustomUserManager()
def __str__(self):
return self.email
My serializers:
class CustomLoginSerializer(LoginSerializer):
username = None
email = serializers.EmailField(required=True)
password = serializers.CharField(style={"input_type": "password"},)
user_type = serializers.IntegerField()
My views:
class VendorLoginUserView(LoginView):
permission_classes = [AllowAny]
serializer_class = CustomLoginSerializer
def post(self, request, *args, **kwargs):
data = request.data
serializer = CustomLoginSerializer(data=data)
data['user_type'] = request.user.user_type
user_type = data['user_type']
if user_type is 2:
serializer.is_valid(raise_exception=True)
new_data = serializer.data
user = serializer.validated_data["user"]
serializer = self.get_serializer(user)
token, created = Token.objects.get_or_create(user=user)
# return response.Response(new_data, status=status.HTTP_200_OK)
return response.Response({"token": token.key,
"serializer.data": serializer.data},
status=status.HTTP_200_OK)
else:
message = "This is not a seller account"
return Response({'message':message,},
status=status.HTTP_400_BAD_REQUEST)
My urls:
path("api/vendorlogin/",views.VendorLoginUserView.as_view(), name='api-vendorlogin'),
Also, do I need to make a separate register view for vendor??
I have a custom user model
class User(AbstractUser):
username = None
email = models.EmailField( unique=True)
phone = models.CharField( max_length=15)
is_pro = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['phone']
objects = UserManager()
#property
def token(self):
"""
Allows us to get a user's token by calling `user.token` instead of
`user.generate_jwt_token().
The `#property` decorator above makes this possible. `token` is called
a "dynamic property".
"""
return self._generate_jwt_token()
def _generate_jwt_token(self):
"""
Generates a JSON Web Token that stores this user's ID and has an expiry
date set to 60 days into the future.
"""
import jwt
from datetime import datetime, timedelta
from django.conf import settings
dt = datetime.now() + timedelta(days=60)
token = jwt.encode({
'id': self.pk,
'exp': int(dt.strftime('%s'))
}, settings.SECRET_KEY, algorithm='HS256')
return token.decode('utf-8')
Now I try make SignIn API with Django Rest Framework using this tutorial https://thinkster.io/tutorials/django-json-api/authentication
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:
model = User
fields = ['email', 'phone', 'password', 'token']
def create(self, validated_data):
# Use the `create_user` method we wrote earlier to create a new user.
return User.objects.create_user(**validated_data)
views.py
class RegistrationAPIView(APIView):
# Allow any user (authenticated or not) to hit this endpoint.
permission_classes = (AllowAny,)
serializer_class = RegistrationSerializer
def post(self, request):
user = request.data.get('user', {})
serializer = self.serializer_class(data=user)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
Then I create a new user an error occured "This field is required." for all my User fields, like email, phone, password.
Screenshot picture http://joxi.ru/12MOMkZt4eeBEr
This is because you set this fields not nullable and required inside User model. To fix it you can add blank=True arguments to the fields which may be blank, like phone:
class User(AbstractUser):
username = None
email = models.EmailField(unique=True)
phone = models.CharField(max_length=15, blank=True)
is_pro = models.BooleanField(default=False)
After this run makemigrations and migrate to apply changes at DB level.
UPD
In view you need to get data from request.data directly:
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
request.data doesn't contain user key, so request.data.get('user', {}) return empty dict.