I have the following code snippet:
user = User(username='h#h.com',email='h#h.com')
user.set_password('pass')
user.save()
u = authenticate(username='h#h.com', password='pass') #this always returns None!!!
The problem is, u is always None. I've followed code samples on other stack overflow posts and have narrowed it down to the above lines.
Any ideas as to what might be happening?
Put something like this in your settings
#Authentication backends
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
or if you are using userena for your accounts
#Authentication backends
AUTHENTICATION_BACKENDS = (
'userena.backends.UserenaAuthenticationBackend',
'guardian.backends.ObjectPermissionBackend',
'django.contrib.auth.backends.ModelBackend',
)
Interestingly enough, check_password returns True in the following:
eml = "4#a.com"
pw = "pass"
uname = 'w2'
user = User.objects.create_user(uname,eml,pw)
user.save()
log.debug("Password check passes?")
log.debug(user.check_password(pw)) # Logs True!!!
user = authenticate(username=uname, password=pw)
Why don't you create a user like this:
user = User.objects.create_user( username="whatever", email="whatever#some.com", password="password")
user = authenticate( username="whatever",password="password")
In settings.py, add
AUTH_USER_MODEL = your custom user class
e.g if django app name is office and custom user class is Account then
AUTH_USER_MODEL = 'office.Account'
set_password is a misleading method, it doesn't save the password on the user table. You need to call user.save() in order for it to work on your flow
You have to check whether user is active? If not, you only set active for user in admin panel, or set when creating user by adding the following line to user model:
is_active = models.BooleanField(default=True)
Also check that you have the right username/password combo. sometimes the one that is created from the createsuperuser command is different than a username you would typically use.
As most of them suggested if we create the user's using User.objects.create_user(**validated_data) this will hash the raw password and store the hashed password. In-case if you you are using User model serializers to validate and create users, it is required to override the serializer method like this
class UserSerializers(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
# this is the method responsible for insertion of data with hashed password
def create(self, validated_data):
return User.objects.create_user(**validated_data)
I puzzled with this problem for four days, and the above answers didn't help.
The problem was that I, as you, was using the user.save() and I could not see what the problem was, but then I looked at it with debug eyes, and it turns out that if you use user.save() it messes with the hashing of the password somehow, don't ask me how I don't know. So I worked around it by using the user.create() method that Django provides, worked like a charm:
#api_view(['POST'])
def create_user(request):
new_user = UserSerializer(data=request.data)
if new_user.is_valid():
user_saved = new_user.create(request.data)
return Response('User {} created'.format(user_saved.username),
status=status.HTTP_200_OK)
else:
return Response('User not created', status=status.HTTP_200_OK)
I used something like this, but you can do as you wish just use the user.create().
Related
I'm trying to change a user's password on my views.py and whenever I change the password, I lose my connection and access to my account
my view.py:
user = User.objects.get(id=request.user.id)
user.password = make_password(request.POST.get("password"))
user.save()
A User object normally has a .set_password(…) method [Django-doc], so you can update that password with:
request.user.set_password(request.POST['password'])
request.user.save()
You can omit fetching the user object, since request.user aleady does that. Using user = User.objects.get(id=request.user.id) is thus an extra query that only is equivalent to request.user.
try using set_password instead of make_password like that
user = User.objects.get(id=request.user.id)
user.password = set_password(request.POST.get("password"))
user.save()
The following is an explanation provided by the Django documentation https://docs.djangoproject.com/en/3.2/topics/auth/default/#changing-passwords
I am new to Djnago and Python.
I created middleware class in Djnago with the name StaffAccessMiddleware
I used social_django app to create user from Gmail and i want to implement
is_staff = True and assign at least one group only if users login in DJango firstTime .
My question is how to access user in middleware and check only first time user will enter in this code in that case i need to assign is_staff = True and assign group once user is created.
I tried to create middle ware class like below.
class StaffAccessMiddleware(object):
def process_request(self, request):
if hasattr(request, 'user') and request.user.is_authenticated():
user = request.user
if groups:
groups[0].name
return None
I would suggest you to use pipeline, something like this:
Add a custom pipeline to update user as is_staff=True
In that pipeline check for is_new parameter and update user only when is_new is True. Social-auth sends is_new=True when user is logging in for first time i.e. when user is created.
Add your custom pipeline in SOCIAL_AUTH_PIPELINE settings.
Then you can restrict some views to staff users only by specifying permission_required settings.
Your final pipeline may look something like this:
def make_new_user_as_staff(backend, user, is_new=False, *args, **kwargs):
if backend.name == 'gmail' and is_new:
user.is_staff = False
user.save()
In settings.py (or settings file)
SOCIAL_AUTH_PIPELINE = (
#other pipelines goes here
"<full-path-to-make_new_user_as_staff-pipeline>",
#some other pipelines goes here
)
Reference : https://python-social-auth-docs.readthedocs.io/en/latest/pipeline.html
Let me know if I have misunderstood your query/this doesn't resolve your issue
I am using Django 1.9. When I tried to add PermissionRequiredMixin to my class-based-view, it seems not to work as expected. I created a new user in a auth_group. This auth_group doesn't have any permission to any apps or models. This new user is not a superuser or admin user. But the app doesn't prevent this user from accessing to a particular view that needs permission_required.
Firstly, here is what I tried to make sure the user doesn't have permission:
user.get_all_permissions() # return set() - empty permission, which is correct.
user.is_superuser # return false, which is correct.
user.has_perm('myapp.add_something or even any words that make no sense') # always return true, which is very weird.
The app has custom user model and also uses django-allauth as the AUTHENTICATION_BACKENDS. I am not sure if PermissionRequiredMixin will check user.has_perm() and it always return true so that's why checking permission doesn't work as expected?
# views.py
class My_View(PermissionRequiredMixin, View):
permission_required = 'polls.can_vote'
def get(self, request, *args, **kwargs):
# do something...
return render(request, "template.html", {})
# models.py - Custom User Model
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
group = models.ManyToManyField(Group, through='UserGroupRelationship')
....
# models.py - many-to-many relationship between user and group
class UserGroupRelationship(models.Model):
user = models.ForeignKey("CustomUser")
user_group = models.ForeignKey(Group)
I also tried the old way to check permission in urls.py. It doesn't prevent user accessing either so I do not think that's the problem of using PermissionRequiredMixin.
urlpatterns = patterns('',
(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)
After spending a few days on this problem, I eventually find out the cause.
When I looked into the source code about PermissionRequiredMixin, I found that PermissionRequiredMixin indeed checks user.has_perm(). When I tried to find the source code of has_perm(), I found that my codes (which is copied from the custom user model example from Django's document) contains the following overridden method...
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
That's reason why user.has_perm('anything') always return true, which also affects the functionality of PermissionRequiredMixin. Therefore, if you are new to Django and try to copy some example codes from document, you need to be very careful about each line...
I have a Client model with a OneToOne relationship to User, to extend the User model.
I need to be able to register a user (with a form that includes both the User and Client fields), and for that I used django-registration. Here is the view for registration, based on some snippets I found:
def register_client(request):
if request.method == 'POST':
userform = UserForm(request.POST, prefix='user')
clientform = ClientForm(request.POST, prefix='client')
if userform.is_valid() and clientform.is_valid():
user = userform.save()
client = clientform.save(commit=False)
client.user = user
client.save()
login(request, user)
return HttpResponseRedirect('/webapp/')
else:
return HttpResponse('error!')
else:
userform = UserForm(prefix='user')
clientform = ClientForm(prefix='client')
t = loader.get_template('register.html')
c = RequestContext(request, {
'userform':userform,
'clientform':clientform,
})
return HttpResponse(t.render(c))
And here are my Forms:
from registration.forms import RegistrationForm
class UserForm(RegistrationForm):
def save(self):
new_user = User.objects.create_user(
username=self.cleaned_data['username'],
email = self.cleaned_data['email'],
password=self.cleaned_data['password1'])
new_user.backend='django.contrib.auth.backends.ModelBackend'
new_user.save()
return new_user
class ClientForm(forms.ModelForm):
class Meta:
model = Client
exclude = ['user']
I implemented the save() method for UserForm, since RegistrationForm doesn't implement one like any typical form.
Why does one have to go through all the trouble to implement some backend in order to just save a form?
Is there any problem with this simple way? It does work.
(I also added the new_user.backend='django.contrib.auth.backends.ModelBackend' so I could login the user automatically after registration.)
I'm not sure how to answer your question. If your code works then I don't see a problem. But as zaphod said, django-registration does the saving and activating of the user for you.. If you want to add extra data to your user then use django-profiles like zaphod suggested too.
I myself use django-userena. It is like django-registration and django-profiles in one.
Why do you need to save the User model? django-registration does it for you, unless you need some different functionality.
If you want to store some extra information per user, it might be better to use User profiles.
So the problem is I have extended User model in django. and I have written views for it.
Here is my models code :-
class StudentProfile(User):
batch = models.CharField(max_length=10)
course = models.CharField(max_length=20)
date_of_birth = models.DateField()
answer = models.CharField(max_length=20)
contact = models.CharField(max_length=20)
here is my auth backend file :-
from quizapp.models import StudentProfile
class StudentAuthenticationBackend(object):
def authenticate(self, username=None, password=None):
try:
student = StudentProfile.objects.get(username=username)
if student.check_password(password):
return student
except StudentProfile.DoesNotExist:
pass
return None
def get_user(self, user_id):
try:
return StudentProfile.objects.get(pk=user_id)
except StudentProfile.DoesNotExist:
return None
And I have made changes in seetings.py
AUTHENTICATION_BACKENDS = (
'quizapp.backends.StudentAuthenticationBackend',
'django.contrib.auth.backends.ModelBackend',
)
I'm printing username,password and authentication user. This is what i got :-
When using django created superuser
>> a = authenticate(username="super",password="super")
>> print(a)
>> super
But when using user created by form,
>> b = authenticate(username="test",password="123")
>> print(b)
>> None
I have cross checked username and password and it's true.
So but in auth_user table, username is super and password is encrypted but for test user, username is user and password is 123.
So the problem must be django is taking 123 is encrypted password and using decrypted version of it to authenticate.
Is there any way to solve this?
I have used OneToOneField and added extra fields in StudentProfile model. Now I'm using forms and registering user with it.
This is the view code :-
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = StudentProfile.objects.create(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
batch=form.cleaned_data['batch'],
first_name=form.cleaned_data['first_name'],
last_name=form.cleaned_data['last_name'],
course=form.cleaned_data['course'],
date_of_birth=form.cleaned_data['date_of_birth'],
secret_question=form.cleaned_data['secret_question'],
answer=form.cleaned_data['answer'],
contact=form.cleaned_data['contact']
)
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {'form': form})
return render_to_response('registration/register.html',variables)
And I'm getting IntegrityError at /register/
null value in column "user_id" violates not-null constraint error.
Is there any way to fix this?
From the Django authenication docs section on storing additional information about users:
If you'd like to store additional information related to your users, Django provides a method to specify a site-specific related model -- termed a "user profile" -- for this purpose.
To make use of this feature, define a model with fields for the additional information you'd like to store, or additional methods you'd like to have available, and also add a OneToOneField named user from your model to the User model. This will ensure only one instance of your model can be created for each User.
So you shouldn't subclass User at all -- that's the root of your problem. Instead, you should create another model with a one-to-one relationship with User and add your fields there.