Anonymous user has no attribute _meta in custom user model - django

I've been facing this problem for so long now and I'm done experimenting. I'm a newbie in Django.
I've been using a custom user model but for some reason this Registration form doesn't work properly. I can't login using the method login(), though it'saving the data fine. Also, the login form doesn't allow any other user login other than the superuser.
Here is the error:
AttributeError at /register/
'AnonymousUser' object has no attribute '_meta'
Request Method: POST
Request URL: http://127.0.0.1:8000/register/
Django Version: 2.2.4
Exception Type: AttributeError
Exception Value:
'AnonymousUser' object has no attribute '_meta'
Exception Location: C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\utils\functional.py in inner, line 257
Python Executable: C:\Users\hello\AppData\Local\Programs\Python\Python37-32\python.exe
Python Version: 3.7.4
Traceback:
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\views\generic\base.py" in dispatch
97. return handler(request, *args, **kwargs)
File "D:\authen\authentica\views.py" in post
40. login(request, user)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\contrib\auth\__init__.py" in login
126. request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
File "C:\Users\hello\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\utils\functional.py" in inner
257. return func(self._wrapped, *args)
Exception Type: AttributeError at /register/
Exception Value: 'AnonymousUser' object has no attribute '_meta'
Here is the code:
models.py
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from django.forms import ModelForm
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class CustomUserManager(BaseUserManager):
use_in_migrations = True
def create_user(self, email, name ,password=None,is_active= True, is_staff=False, is_admin=False):
if not name:
raise ValueError("Users must've a name")
if not email:
raise ValueError("Users must've a email")
if not password:
raise ValueError("User must've a password")
user_obj= self.model(
email=self.normalize_email(email) ,
name= name
)
user_obj.set_password(password) # Change password for the User
user_obj.staff= is_staff
user_obj.admin= is_admin
user_obj.active= is_active
user_obj.save(using =self._db)
return user_obj
def create_staffuser(self,email, name ,password=None):
user= self.create_user(
email,
name,
password=password,
is_staff= True
)
return user
def create_superuser(self,email, name ,password=None, **extra_fields):
extra_fields.setdefault('is_superuser', True)
user = self.create_user(
email,
name,
password=password,
)
user.staff = True
user.admin = True
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser, PermissionsMixin):
name = models.CharField(max_length=255)
email = models.CharField(max_length=254, unique=True)
active = models.BooleanField(default= True)
staff = models.BooleanField(default= False)
admin = models.BooleanField(default= False)
timestamp= models.DateTimeField(auto_now_add=True)
USERNAME_FIELD ='email'
REQUIRED_FIELDS= []
objects= CustomUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email, self.name
def has_perm(self, perm, obj=None):
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
return self.staff
#property
def is_admin(self):
return self.admin
#property
def is_active(self):
return self.active
views.py
class RegisterView(TemplateView):
template_name= 'authentica/register.html'
def get(self, request):
user= request.user
if user.is_authenticated:
return redirect('home')
else:
form = RegisterForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
if request.POST:
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
user = authenticate(email=email ,password=password) #django built in authentication
login(request, user)
return redirect('home')
else:
form = RegisterForm()
return render(request, self.template_name, {'form': form})
forms.py
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ('email', 'name')
# def clean_name(self):
# name= self.cleaned_data.get('name')
# qs= CustomUser.objects.get('name')
# if qs.exists():
# raise forms.ValidationError('Name is taken')
# return name
def clean_email(self):
email = self.cleaned_data.get('email')
qs = CustomUser.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2

You're not saving the password for the user. Your custom RegisterForm is a ModelForm for CustomUser that only saves the fields email and name.
So when you authenticate() your user, this fails and returns None.
Your next step is to login() the user, which is None and produces the error you see.
Inherit from django.contrib.auth.forms.UserCreationForm instead of ModelForm. That will spare you a lot of code (e.g. you don't have to define the password1 and password2 fields, nor clean_password2) and correctly save your user.

Related

AttributeError at /register Manager isn't available; 'auth.User' has been swapped for 'account.Account'

I have been working on debugging this code for last 2 days but not able to find out the mistake. I have seen the tried the user = get_user_model() but it is not working.
Also i have added in settings
AUTH_USER_MODEL = 'account.Account'
and account is a registered app in settings.
models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
from django.conf import settings
# account manager
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, profile, 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,
profile_image=profile
)
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),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
# models here.
def uploadImageHandler(instance,filename):
fpath = pathlib.Path(filename)
newFileName = str(uuid.uuid1())
return f"images/profile/{newFileName}{fpath.suffix}"
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
firstName = models.CharField(max_length=30)
lastName = models.CharField(max_length=30)
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(max_length=255, upload_to=uploadImageHandler, null=True, blank=True)
hide_email = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate , login , logout
# import from app
from account.models import Account
class RegistrationForm(UserCreationForm):
email = forms.EmailField(max_length=255, required=True, help_text="Enter a valid email ")
class meta:
model = Account
fields = ('email','username','password1','password2','profile')
def clean_email(self):
email = self.cleaned_data["email"].lower()
try:
account = Account.objects.get(email=email)
except:
return email
raise forms.ValidationError(f"email{email} is already in use.")
def clean_username(self):
username = self.cleaned_data["username"]
try:
account = Account.objects.get(username=username)
except:
return username
raise forms.ValidationError(f"email{username} is already in use.")
views.py
# django imports
from django.shortcuts import render , HttpResponse, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
# app imports
from .forms import RegistrationForm
# Create your views here.
user = get_user_model()
# register page here
def register_view(request, *args, **kwargs):
context = {}
user = request.user
if user.is_authenticated:
return redirect("home")
elif (request.method == 'POST'):
print("hello")
form = RegistrationForm(request.POST)
print(form)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email').lower()
raw_password = form.cleaned_data.get('password1')
account = authenticate(email=email,password=raw_password)
login(request,account)
destination = kwargs.get("next")
if destination:
return redirect(destination)
else:
pass
else:
context['registration_form'] = form
else:
form = RegistrationForm()
context['registration_form'] = form
return render(request, 'account/register.html',context)
error
Traceback (most recent call last):
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/mnt/d/Working/artoction/artoction/account/views.py", line 54, in register_view
print(form)
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/utils/html.py", line 376, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 132, in __str__
return self.as_table()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 270, in as_table
return self._html_output(
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 193, in _html_output
top_errors = self.non_field_errors().copy()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 304, in non_field_errors
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 170, in errors
self.full_clean()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/forms.py", line 374, in full_clean
self._post_clean()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/contrib/auth/forms.py", line 117, in _post_clean
super()._post_clean()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/forms/models.py", line 413, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/db/models/base.py", line 1223, in full_clean
self.clean()
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/contrib/auth/models.py", line 371, in clean
self.email = self.__class__.objects.normalize_email(self.email)
File "/mnt/d/Working/artoction/artenv/lib/python3.10/site-packages/django/db/models/manager.py", line 187, in __get__
raise AttributeError(
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'account.Account'
error as shown in the browser
The problem comes from your register view, you have imported the "from django.contrib.auth import get_user_model" and "from django.contrib.auth.models import User" which you need to take out from your imports models.
# django imports
from django.shortcuts import render , HttpResponse, redirect
from django.contrib.auth import authenticate, login
#from django.contrib.auth.models import User this where where your problem comes from
# from django.contrib.auth import get_user_model
# now you would need to import the Account model since you are not using djangos build in User model
from account.models import Account
# app imports
from .forms import RegistrationForm
# Create your views here.
# user = get_user_model() You would have to delete this or just comment it out .
# register page here
def register_view(request, *args, **kwargs):
context = {}
user = request.user
if user.is_authenticated:
return redirect("home")
elif (request.method == 'POST'):
print("hello")
form = RegistrationForm(request.POST)
print(form)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email').lower()
raw_password = form.cleaned_data.get('password1')
account = authenticate(email=email,password=raw_password)
login(request,account)
destination = kwargs.get("next")
if destination:
return redirect(destination)
else:
pass
else:
context['registration_form'] = form
else:
form = RegistrationForm()
context['registration_form'] = form
return render(request, 'account/register.html',context)
I also observed that you have an attribute in your models manager filed which is not in your account field, which in think would raise exception of attribute error when your try to create an account so i so guess you delete the profile attribute from your manager and also from your form. Here is my solution .
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')
Your form.py: Everything should now work perfectly hopefully!
class RegistrationForm(UserCreationForm):
email = forms.EmailField(max_length=255, required=True, help_text="Enter a valid email ")
class meta:
model = Account
fields = ('email','username','password1','password2')
def clean_email(self):
email = self.cleaned_data["email"].lower()
try:
account = Account.objects.get(email=email)
except:
return email
raise forms.ValidationError(f"email{email} is already in use.")
def clean_username(self):
username = self.cleaned_data["username"]
try:
account = Account.objects.get(username=username)
except:
return username
raise forms.ValidationError(f"email{username} is already in use.")
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),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user

Set the groups in Django template

I want to register users by using template, i want also, in the moment of registration, set the group(default groups permission provided by Django) of every new user created, I set the group of user in the template but when i look to the group of user in the database i I found it empty.
class ProfileUserManager(BaseUserManager):
def create_user(self, username, password,**extra_fields):
user = self.model(username=username, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, password,**extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username,password,**extra_fields)
class ProfileUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
username = models.CharField(max_length=255,unique=True)
first_name=models.CharField(max_length=255)
last_name= models.CharField(max_length=255)
departement= models.CharField(max_length=255)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
objects = ProfileUserManager()
def __str__(self):
return self.username
forms.py
class FormAddAccount(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
fields = ('email', 'password1', 'password2', 'is_staff','username','groups','first_name','last_name','departement')
first, you create decoratorsy.py in your app then add the following code in decorators.py
from django.http import HttpResponse
from django.shortcuts import redirect
def unauthenticated_user(view_func):
def wrapper_func(request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('url')
else:
return view_func(request, *args, **kwargs)
return wrapper_func
def allowed_users(allowed_roles=[]):
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group in allowed_roles:
return view_func(request, *args, **kwargs)
else:
return HttpResponse('You are not authorized to view this page')
return wrapper_func
return decorator
def admin_only(view_func):
def wrapper_function(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group == 'GroupName':
return redirect('url')
if group == 'admin':
return view_func(request, *args, **kwargs)
return wrapper_function
views.py
def createuser(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
user = form.save()
username = form.cleaned_data.get('username')
group = Group.objects.get(name='GroupName')
user.groups.add(group)
Customer.objects.create(
user=user, )
messages.success(request, 'Account was created for ' + username)
return redirect('login')
context = {'form': form}
return user
on your views.py you add #allowed_users(allowed_roles=['GROUPNAME'])
for the permission, that group see the following things
I just add some lines of code to Views.py when i add a user:
def createView(request):
form=FormAddAccount()
if request.method=="POST":
form=FormAddAccount(request.POST)
if form.is_valid():
user=form.save()
for element in form.cleaned_data["groups"] :
group = Group.objects.get(name=element)
user.groups.add(group)
user.save()
redirect("accounts/list.html")
context={
'form':form
}
return render(request,"accounts/addaccount.html",context)

How to return user details in response after login in django rest_framework

Hi I am beginner in Django Here I want user email and name in response after user login using api. Thanks in advance for your help.
models.py
I want user email and user name in response only getting auth token in response
class UserManager(BaseUserManager):
def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
if not password:
raise ValueError('Users must have a password')
user = self.model(email=self.normalize_email(email), **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email,password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
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 = UserManager()
USERNAME_FIELD = 'email'
serializers.py
I want user email and user name in response only getting auth token in response
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
class Meta:
model = get_user_model()
fields = ('email', 'password', 'name')
extra_kwargs = {'password': {'write_only': True, 'min_length': 6}}
def create(self, validated_data):
user = User.objects.create_user('name',validated_data['email'],
validated_data['password'],)
return user
class AuthTokenSerializer(serializers.Serializer):
email = serializers.CharField()
password = serializers.CharField(
style = {'input_type':'password'},
trim_whitespace = False
)
def validate(self, attrs):
email = attrs.get('email')
password = attrs.get('password')
user = authenticate(
request = self.context.get('request'),
username = email,
password = password
)
if not user:
msg = _('Unable to authenticate with provided crenditial')
raise serializers.ValidationError(msg, code = 'authorization')
attrs['user'] = user
return attrs
urls.py
I want user email and user name in response only getting auth token in response
path('api/login/',views.CreateTokenView.as_view(),name='token'),
View file for creating view and I dont now how to return user from Auth token. I want user email and user name in response only getting auth token in response
views.py
class UserCreate(APIView):
"""
Creates the user.
"""
def post(self, request, format='json'):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
token = Token.objects.create(user=user)
json = serializer.data
json['token'] = token.key
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CreateTokenView(ObtainAuthToken):
serializer_class = AuthTokenSerializer
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
def post(self, request, *args, **kwargs):
response = super(CreateTokenView, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
return Response({'token': token.key})
I guess what you can do is maybe once you recieve a valid token for the user, you could query for the user using the user's email from the request data.
def post(self, request, *args, **kwargs):
response = super(CreateTokenView, self).post(request, *args, **kwargs)
token = Token.objects.get(key=response.data['token'])
user_email = request.data.get('email', None)
user = User.objects.get(email=user_email)
return Response({'name': user.name, 'email': user.email, 'token': token.key})
Hope this helps!
I know this is an old post but I ended up searching for this.
For the new comers:
There's an example on Django REST Framework, available here
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
class CustomAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'email': user.email
})

django 2 Custom User: Attribute Error (password not passing/hashing properly)

I have implemented a custom user setup for django 2. However I can't seem to find out source of this error that occurs anytime I attempt to register.
AttributeError at /register/
'AnonymousUser' object has no attribute '_meta'
When I get this error, the password is passed without a hash and not saved to the db, while the other values pass through fine.
models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import ugettext_lazy as _
class MyUserManager(BaseUserManager):
def _create_user(self, email, password):
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email,)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this 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.'
),
)
USERNAME_FIELD = 'email'
objects = MyUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm
from django.contrib import messages
from . forms import RegisterForm
def home(request):
return render(request, 'authenticate/home.html', {})
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ('Welcome Back'))
return redirect('home')
else:
messages.success(request, ('No account matches those credentials. Please try again.'))
return redirect('login')
else:
return render(request, 'authenticate/login.html', {})
def logout_user(request):
logout(request)
messages.success(request, ('Successfully logged out'))
return redirect('home')
def register_user(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data['email']
password = form.cleaned_data['password1']
user = authenticate(email=email, password=password)
login(request, user)
messages.success(request, ('Welcome to Keto2Go!'))
return redirect('home')
else:
form = RegisterForm()
context = {'form': form}
return render(request, 'authenticate/register.html', context)
def edit_profile(request):
if request.method == 'POST':
form = UserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
messages.success(request, ('You have updated your profile'))
return redirect('home')
else:
form = UserChangeForm(instance=request.user)
context = {'form': form}
return render(request, 'authenticate/edit_profile.html', context)
def change_password(request):
if request.method == 'POST':
form = PasswordChangeForm(data=request.POST, user=request.user)
if form.is_valid():
form.save()
messages.success(request, ('Your password has been updated.'))
return redirect('home')
else:
form = PasswordChangeForm(user=request.user)
context = {'form': form}
return render(request, 'authenticate/change_password.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from . models import User
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
def clean_password2(self):
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
class UserAdminCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_password2(self):
# Check that the two password entries match
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data and self.cleaned_data['password1'] != self.cleaned_data['password2']:
raise forms.ValidationError("The password does not match ")
return self.cleaned_data
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('email', 'password')
def clean_password(self):
return self.initial["password"]
In registration, you are trying to authenticate using keyword argument email but authenticate does not have any kwargs email, it takes username and password(Unless you override it in custom backend). So try like this(Just like your login_user view):
authenticate(request, username=email, password=password)
See in documentation for more details.
Also you password will not be saved in hash format, because you are directly saving it to Database using save method without using set_password. You need to update the save method in Registration form(Just like your UserAdminCreationForm)
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user

Handle a request header in Django rest framework to get the secret key passed in the header and save it with User table?

I have a django backend for a mobile app.
I'm using django rest framework (django-rest-auth), but I'm still writing my own views and logic because the API endpoints are not model based.
The request sent to me has a secret key in the headers which is associated to individual devices registered. Along with it it has post data consisting of device id and other details.
Once I get that header using request.META how can Save it in User model(It'll update everytime user login), so later it can be used as a foreign key to getting all the details like user and associated device.
class CustomLoginView(LoginView):
def get_response_serializer(self):
if getattr(settings, 'REST_USE_JWT', False):
response_serializer = JWTSerializer
else:
# print(self.request.data)
response_serializer = serializers.TokenSerializer
# response_serializer = {'data':response_serializer}
return response_serializer
def get_response(self):
# raise APIException("There was a problem!")
serializer_class = self.get_response_serializer()
# print(serializer_class.data)
try:
if getattr(settings, 'REST_USE_JWT', False):
data = {
'user': self.user,
'token': self.token
}
serializer = serializer_class(instance=data,
context={'request': self.request})
else:
print("hello")
serializer = serializer_class(instance=self.token,
context={'request': self.request})
print("BYE")
print(serializer.data)
# print(self.request.data)
try:
# print(serializer.data)
if 'email' not in self.request.POST:
return Response({'data':'message'})
return Response({'data':serializer.data,'status':1,'message':'Success'}, status=status.HTTP_200_OK)
except ValidationError as exc:
raise ValidationError({
'field_val1': exc.detail,
})
except:
print("in except")
raise APIException("There was a problem!")
def post(self, request, *args, **kwargs):
self.request = request
self.serializer = self.get_serializer(data=self.request.data,
context={'request': request})
print(self.request.data)
if self.serializer.is_valid():
print(request.META)
self.login()
return self.get_response()
else:
return Response({"data":[],"message":"Credentials are wrong",'status':0})
My User_Model
class User(AbstractUser):
"""User model."""
username = None
email = models.EmailField(_('email address'), unique=True)
mobile_token = models.CharField(max_length=20,blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
My UserManage()
class UserManager(BaseUserManager):
"""Define a model manager for User model with no username field."""
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""Create and save 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.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
"""Create and save a regular User with the given email and password."""
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=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)
Define an instance method and use it wherever in your CustomLoginView as
from rest_framework.exceptions import ValidationError
class CustomLoginView(LoginView):
def save_header(self):
headr = self.request.META.get('HTTP_MYHEADER', None)
if headr is None:
raise ValidationError('"MYHEADER" is missing in headers"')
current_user = self.user
current_user.mobile_token = headr
current_user.save()
# your code
UPDATE
Change your view as below
from rest_auth.views import LoginView
from rest_framework.exceptions import ValidationError
class CustomLoginView(LoginView):
def save_header(self):
headr = self.request.META.get('HTTP_MYHEADER', None)
if headr is None:
raise ValidationError('"MYHEADER" is missing in headers"')
current_user = self.user
current_user.mobile_token = headr
current_user.save()
def post(self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
if response.status_code == 200:
self.save_header()
return response
and your payload should be as
{
"email":"myemail#email.com",
"password":"mypassword"
}
Screenshots
1. How to add HEADER
2. How to send data in POSTMAN