I have a post_save signal which is failing with 'expected string or bytes-like object'. I am not sure why, it is being caused by the call to create_user below:-
This is to create a user within a tenant schema for a newly created tenant:
#receiver(post_save, sender=Client)
def create_user(sender, instance, created, **kwargs):
if created:
tenant=instance
with schema_context(tenant):
name = 'name'
email = 'name#email.com'
password = 'passwordexample'
user = CustomUser.objects.create_user(name, email, password)
The underlying user manager which throws the exception is
def create_user(self, name, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
name = self.normalize_email(name)
email = self.normalize_email(email)
user = self.model(name=name, email=email, **extra_fields)
user.set_password(password)
user.save()
return user
This seems to fail on user.save() in the above manager
Any help or pointers greatly appreciated
Thank you
I think the problem you are facing not in Custom user manager it is in
with schema_context(tenant)
as this schema_context takes schema name not tenant
so I think you need to pass schema_name
or if you know tenants use
the following instead
from django_tenants.utils import tenant_context
with tenant_context(tenant):
# All commands here are ran under the schema from the `tenant` object
Related
This is my code in views.py
if form.is_valid():
print(form.cleaned_data)
username = form.cleaned_data.get("username")
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
new_user = User.objects.create_user(username, email, password)
Here is what is printed from the line 'print(form.cleaned_data)'
{'full_name': 'Ross', 'email': 'tree34-5#hotmail.com', 'profilepicture': None, 'password1': 'tree', 'password2': 'tree'}
Here is my code from models.py
class UserManager(BaseUserManager):
def create_user(self, email, full_name=None, password=None, is_active=True, is_staff=False, is_admin=False):
print(email)
if not email:
raise ValueError("Users must have an email address")
'print(email)' returns None. I don't understand why 'print(email)' is not returning tree34-5#hotmail.com. I keep getting the error message "Users must have an email address".
Based on this:
def create_user(self, email, full_name=None, password=None, is_active=True, is_staff=False, is_admin=False):
the first parameter you pass in should be email. But based on your code:
new_user = User.objects.create_user(username, email, password)
you are passing in a "username" instead of an email. That's the major problem.
You might consider to use "form.save()" instead of calling a method.
Your form.cleaned_data does not contain a username field hence None is returned with
form.cleaned_data.get("username")
You then set your email field to the username value as you have e-mail as a positional argument and passed in username as the first argument in this line
new_user = User.objects.create_user(username, email, password)
Change that line to the one below, this should get you what you want. It will unpack the dictionary into the arguments in the function automatically.
new_user = User.objects.create_user(**form.cleaned_data)
Adding to Wind's answer: if you insist on using User.objects.create_user(username, email, password), you must change your create_user to this:
def create_user(self, full_name=None, email, password=None, ...):
The reason why is that Django's create_user does not provide keyword arguments and therefore you must place everything in order. You need to swap the arguments "username" and "email" instead of simply replacing it otherwise the "password" parameter wouldn't work also.
Reference
I have a custom user model based off of AbstractUser and, I use a custom UserManager, I don't know if theres anything special I have to do to get authenticate to work. I know the user is in the db because I can do objects.get(username, password) and it will return the object.
class PassThroughFarmerManager(PassThroughManagerMixin, UserManager):
use_in_migrations = False
class Farmer(FarmStateble, MapPointable, LastRequestStorable, AbstractUser):
last_irrigation_cycle = models.DateTimeField(auto_now_add=False, auto_now=False, null = True, blank=True)
objects = PassThroughFarmerManager.for_queryset_class(FarmerQuerySet)()
Here is an example of my console output,
>>> models.Farmer.objects.get(username='901e2ac5-9324-11e5-81bf-c42c0323e33a').password
u'1223'
>>> u = authenticate(username = '901e2ac5-9324-11e5-81bf-c42c0323e33a', password = '1223')
>>> u
>>> type(u)
<type 'NoneType'>
When you use MyUserModel.objects.create(...), the password is stored in the database in plain text. The call to authenticate does not work, because Django expects the password to be hashed in the database.
Therefore, when you create a user, you need to ensure that the password is hashed, rather than being stored in plain text in the database. You can do this by calling user.set_password('new_password').
The full example in the docs shows a create_user manager method that calls set_password when creating the user. You would then use MyUserModel.objects.create_user(...) instead of MyUserModel.objects.create(...).
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
I am using Python socia auth for face-book. I have modified default Django behavior of User Model and removed username field .
I have added this in custom user model : USERNAME_FIELD = 'email'
BUt I am getting this error when trying to login
TypeError at /complete/facebook/
'username' is an invalid keyword argument for this function
I know when it is trying to create user it doesn't find username field and this throwing this error.
I have defined below settings but still my issue remains as it is :
SOCIAL_AUTH_USER_MODEL = 'accounts.User'
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
Any solution for this ?
I know it's few months since the question was posted, but I hit the same problem and found the solution.
This problem can be solved using pipeline. The default pipeline does this:
def create_user(strategy, details, user=None, *args, **kwargs):
if user:
return {'is_new': False}
fields = dict((name, kwargs.get(name) or details.get(name))
for name in strategy.setting('USER_FIELDS',
USER_FIELDS))
if not fields:
return
return {
'is_new': True,
'user': strategy.create_user(**fields)
}
Override USER_FIELDS in your settings end leave only email. Alternatively you can create completely new create_user method.
i have same issue and solved problem by adding user argument in create user field ..
None: Argument 'username' is needed for social-auth. It is not actually used.
class UserManager(BaseUserManager):
def create_user(self, email,username=None, full_name=None, password='&btCqv"}#,4TWd6A'):
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),
)
user.set_password(password) # change user password
user.staff = is_staff
user.admin = is_admin
user.is_active = is_active
user.save(using=self._db)
return user
if still problem persist refer: https://github.com/python-social-auth/social-app-django/issues/15#issuecomment-276118574
class BmUserManager(BaseUserManager):
def create_user(self, useremail, display_name, password=None):
if not useremail:
raise ValueError('Users must have an email address')
user = self.model(useremail=BmUserManager.normalize_email(useremail))
user.display_name = display_name
user.email = useremail
user.set_password(password)
user.save(using=self._db)
return user
what is the use of self.model(useremail=BmUserManager.normalize_email(useremail))?
The model attribute of a model manager is just a reference to the model class the manager has been created for. In this case it refers to whatever user model that will use this manager.
Here self.model is refering to the model that you are using (kind of Custom User).And the method inside BaseUserManager.normalize_email is used to convert the domain of email in lowercase. For Example if you have email like "Amanmishra1321#GMAil.com", then it will convert the email into "Amanmishra1321#gmail.com"
I am trying to modify my Django project authentication so I can use my own User model.
I have got it working so far, however I am unable to override the "password" field. I want to change the name to "password_hash".
I have tried this manager:
class UserManager(BaseUserManager):
def create_user(self, email_address, full_name, password=None):
if not email_address:
raise ValueError('Users must have an email address')
user = self.model(
email_address = self.normalize_email(email_address),
full_name = full_name,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email_address, full_name, password_hash):
user = self.create_user(email_address,
password_hash=password_hash,
full_name=full_name,
)
user.is_admin = True
user.save(using=self._db)
return user
However I get the error TypeError: create_superuser() got an unexpected keyword argument 'password'.
How do I stop create_superuser() from expecting "password" and change it to "password_hash". For username I did it by changing the USERNAME_FIELD, however nothing in the documentation suggests a similar method for the password.
Thanks in advance,
Mark
The solution that worked for me was to override this method in my new user model:
def set_password(self, raw_password):
self.password = make_password(raw_password)