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
Related
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
I'm trying to develop a website for an online store, and after creating and registering models, I don't know why, this error is thrown. What can I do? And also after running the migrate command, it is saying no migrations to apply. How can I do this?
My models.py:
from django.db import models
import stripe
from django.conf import settings
from django.contrib.auth.signals import user_logged_in
from django.contrib.auth.models import User
stripe.api_key = settings.STRIPE_SECRET_KEY
class UserStripe(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
stripe_id = models.CharField(max_length=120)
def __unicode__(self):
return str(self.stripe_id)
def get_or_create_stripe(sender, user, *args, **kwargs):
try:
user.userstripe.stripe_id
except UserStripe.DoesNotExist:
customer = stripe.Customer.create(
email = str(user.email)
)
new_user_stripe = UserStripe.objects.create(
user = user,
stripe_id = customer.id
)
except:
pass
user_logged_in.connect(get_or_create_stripe)
Have you changed anything since your last migration ?
I think you might have changed some models, now django is unable to find your table.
I would delete the current migration files and create new ones.
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/
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.
I have a Django application and the custom user - want to test it (do unit testing). My custom user is emailuser, which consists of e-mail and password fields. I want to set up something of such national mplayer, give it a field and a password. But my code below does not work.
settings.py
AUTH_USER_MODEL = 'custom_user.EmailUser'
My code in test.py
from django.test import TestCase
from django.conf import settings
class MyTest(TestCase):
def setUp(self):
self.user = settings.AUTH_USER_MODEL.objects.create('testuser#test.pl', 'testpass')
def test_user(self):
self.assertEqual(self.user, 'testuser#test.pl')
Well, try this:
from django.test import TestCase
from django.contrib.auth import get_user_model
User = get_user_model()
class CustomUserTestCase(TestCase):
def test_create_user(self):
# params = depends on your basemanager’s create_user methods.
user = User.objects.create(**params)
self.assertEqual(user.pk, user.id)
You should use the create_user() method instead of just create(). Also you should check the email field, not the user itself.
class MyTest(TestCase):
def setUp(self):
self.user = settings.AUTH_USER_MODEL.objects.create_user(
'testuser#test.pl', 'testpass')
def test_user(self):
self.assertEqual(self.user.email, 'testuser#test.pl')