'user' not available in template django - python

I am using a custom user model with builtin and custom authentication backends. the default for username-password login and the custom one for uid based login The login is working fine but the 'user' (Other than superuser) is not available in the template.Nor is the last_login getting updated in database. Here is my code
backend.py
from support.models import CustomUser
class UsernameIdModelBackend(object):
def authenticate(self, request, uid=None):
try:
user= CustomUser.objects.get(uid=uid)
return user
except CustomUser.DoesNotExist:
return None
def get_user(self, user_id):
try:
return CustomUser.objects.get(pk=user_id)
except CustomUser.DoesNotExist:
return None
models.py
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
uid = models.CharField(max_length=50)
Where did i go wrong..
EDIT :
I was using if user.is_authenticated before the 'user'. After removing the if condition i am seeing AnonymousUser.

Related

Django: user.has_perm always returns false

I have a custom user:
from django.contrib.auth.models import AbstractUser
# Create your models here.
class TaborUser(AbstractUser):
email = models.EmailField('E-mail', unique=True)
Its backend:
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth import get_user_model
from django.db.models import Q
UserModel = get_user_model()
class EmailBackend(BaseBackend):
def get_user(self, user_id):
user = UserModel.objects.filter(pk=user_id)
breakpoint()
if user:
return user[0]
else:
return None
def authenticate(self, request, username=None, password=None, **kwargs):
user = UserModel.objects.filter(email=username)
if not user:
user = UserModel.objects.filter(username=username)
# Both username and e-mail are unique. As long as we don't have
# a very rogue admin, we should be alright.
if user:
user = user[0]
else:
return None
if user.check_password(password):
return user
else:
return None
The model does not seem to pass this check:
class AdminView(PermissionRequiredMixin, FormView):
form_class = UploadFileForm
template_name = "admin.html"
login_url = "/login/"
permission_required = ("taborapp.view_photomodel",
"taborapp.add_photomodel",
"taborapp.delete_photomodel",
)
When user is added as follows:
from taborapp.models import TaborUser
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
user = TaborUser.objects.create_user("test")
user.email = "test#example.me"
user.set_password("LOLaPublicPassword123")
permissions = []
photo_type = ContentType.objects.get(app_label="taborapp", model="photomodel")
for codename in "view_photomodel", "add_photomodel", "delete_photomodel":
perm = Permission.objects.filter(content_type=photo_type, codename=codename)
permissions.append(perm[0])
user.user_permissions.add(*permissions)
user.save()
Am I doing anything wrong? I went over docs and similar issues on stack overflow a few times and I just cannot figure out the issue.
I am too brief for the auto-detection system to believe me that I have described my problem enough. I hope this sentence will satisfy it.
Drop into the Django shell:
python manage.py shell
Next,
from django.contrib.auth.models import User
u = User.objects.get(email="test#example.me")
u.get_user_permissions()
Hopefully you'll see what you're looking for in the data returned. That'll give you a good idea of where to look next.
As pointed out by #RiverRook, getting the list of permissions was very helpful as I managed to find the correct thread about this.
Django user get_all_permissions() is empty while user_permissions is set

Can't create a custom User model in django

I have a custom passwordless user model built in django 1.11. user model looks like this
class User(models.Model):
email = models.EmailField(primary_key=True)
REQUIRED_FIELDS = []
USERNAME_FIELD = 'email'
is_anonymous = False
is_authenticated = True
It's a custom user model and depends on a custom auth backend, given like this
class PasswordlessAuthenticationBackend():
def authenticate(self, uid):
try:
token = Token.objects.get(uid=uid)
return User.objects.get(email=token.email)
except User.DoesNotExist:
return User.objects.create(email=token.email)
except Token.DoesNotExist:
return None
def get_user(self, email):
try:
return User.objects.get(email=email)
except User.DoesNotExist:
return None
The auth is registered and working fine. The token is just this
class Token(models.Model):
email = models.EmailField()
uid = models.CharField(default=uuid.uuid4, max_length=40)
The problem is, when I try to call auth.login in my TestCase, it always throws this error:
ValueError: The following fields do not exist in this model or are m2m fields: last_login
What are m2m fields? How and where do I specify this last_login?
Edit:
The failing test looks like this:
from django.test import TestCase
from django.contrib.auth import get_user_model
from django.contrib import auth
from accounts.models import Token
User = get_user_model()
email = 'test#testing.com'
class UserModelTestcase(TestCase):
def test_user_is_valid_with_email_only(self):
user = User(email=email)
user.full_clean()
def test_email_is_primary_key(self):
user = User(email=email)
self.assertEqual(user.pk,email)
def test_links_user_with_auto_generated_uid(self):
token1 = Token.objects.create(email=email)
token2 = Token.objects.create(email=email)
self.assertNotEqual(token1.uid, token2.uid)
def test_no_problem_with_auth_login(self):
user = User.objects.create(email=email)
user.backend = ''
request = self.client.request().wsgi_request
auth.login(request, user) #should not raise, fails!
this link Error about Django custom authentication and login?
has an in-depth explanation about your problem an has multiple solutions you can pick.

How to acces to a model related to a user in DJango

I would like to access to a model related to a user in User. I know that it's possible to get the username or the name of the user using: request.user.get_username()
model.py
class Profile(models.Model):
profile_user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
profile_note = models.CharField(max_length=30,...)
Is there any method to take the related model field without a query?
Example: request.user.profile.profile_note
If you want request.user to always have .profile available without an additional query you can write your own authentication backend that uses select_related when looking up the user so that there is only 1 database query
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class ProfileBackend(ModelBackend):
def get_user(self, user_id):
UserModel = get_user_model()
try:
return UserModel._default_manager.select_related('profile').get(pk=user_id)
except UserModel.DoesNotExist:
return None
settings.py
AUTHENTICATION_BACKENDS = [
'app.backends.ProfileBackend',
]
Now when request.user is loaded from the DB, the profile will be loaded in the same query. You can now access request.user.profile.profile_note without any additional queries

How to create an authentication system in django for a SQLServer database?

I am recently working in a django project with a SQLServer database. I already connected the database with SQLServer, and I want to make an authentication system for a table I have in that database.
I know django comes with a built-in authentication system, but there is no way to tell django to use a specific table in the database to make the authentication, it just seems to look for users in the default admin page.
Is there any way for django to look for data inside a specific table in a SQLServer database and validate the information put by an user?
You can do it by implementing you own user model and then telling django how to authenticate the user. Your model should look something like this:
class Users(models.Model):
id = models.IntegerField(primary_key=True)
is_active = models.IntegerField(default=1)
date_joined = models.DateTimeField(default=timezone.now)
last_login = models.DateTimeField(default=timezone.now)
username = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=30)
#property
def is_authenticated(self):
return True
You can add extra fields, but those are required by django. The property is_authenticated shall always return true, as defined in the documentation.
Next step is to define how will your login authenticate. Create a file name backends.py anywhere in your project and inside of it declared two methods: authenticate and get_user, it should something like this:
from django.contrib.auth.backends import ModelBackend
from users.models import Users
from django.contrib.auth.hashers import *
from login.util import *
class PersonalizedLoginBackend(ModelBackend):
def authenticate(self, request=None, username=None, password=None, **kwars):
#Here define you login criteria, like encrypting the password and then
#Checking it matches. This is an example:
try:
user = Users.objects.get(username=username)
except Users.DoesNotExist:
return None
if check_password(password, user.password):
return user
else:
return None
def get_user(self, user_id):
#This shall return the user given the id
from django.contrib.auth.models import AnonymousUser
try:
user = Users.objects.get(id=user_id)
except Exception as e:
user = AnonymousUser()
return user
Now you need to tell django that where is the backends located, on your settings.py:
AUTHENTICATION_BACKENDS = (
# ... your other backends
'path.to.backends.PersonalizedLoginBackend',
)
From there you should be able to do your login like normal, first authenticate and then use do_login function.
Read more details in here:
https://docs.djangoproject.com/en/2.2/topics/auth/customizing/

Why User model inheritance doesn't work properly?

I'm trying to use a User model inheritance in my django application. Model looks like this:
from django.contrib.auth.models import User, UserManager
class MyUser(User):
ICQ = models.CharField(max_length=9)
objects = UserManager()
and authentication backend looks like this:
import sys
from django.db import models
from django.db.models import get_model
from django.conf import settings
from django.contrib.auth.models import User, UserManager
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
class AuthBackend(ModelBackend):
def authenticate(self, email=None, username=None, password=None):
try:
if email:
user = self.user_class.objects.get(email = email)
else:
user = self.user_class.objects.get(username = username)
if user.check_password(password):
return user
except self.user_class.DoesNotExist:
return None
def get_user(self, user_id):
try:
return self.user_class.objects.get(pk=user_id)
except self.user_class.DoesNotExist:
return None
#property
def user_class(self):
if not hasattr(self, '_user_class'):
self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 2))
if not self._user_class:
raise ImproperlyConfigured('Could not get custom user model')
return self._user_class
But if I'm trying to authenticate - there is an "MyUser matching query does not exist" error on the self.user_class.objects.get(username = username) call. It looks like admin user created on base syncing (I'm using sqlite3) stores into User model instead of MyUser (username and password are right). Or it's something different?
What I'm doing wrong? This is an example from http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Contrary to what the blog post you linked to says, storing this kind of data in a profile model is still the recommended way in Django. Subclassing User has all kinds of problems, one of which is the one you are hitting: Django has no idea you have subclassed User and happily creates and reads User models within the Django code base. The same is true for any other 3rd party app you might like to use.
Have a look at this ticket on Django's issue tracker to get some understanding of the underlying problems of subclassing User

Categories

Resources