Django user model username (unique=False) - python

I have seen many of the solution but none of it seems to be answering the question.
My user model is using AbstractUser right now. Is there a way to make username(unique = False)
Since i wanted to allow user to ba able to have duplication of same username, as the login im am using is by email address and password
Below is the code that i tried but doesnt work.
Code:
class MyUser(AbstractUser):
username = models.CharField(max_length=30, unique=False)
error:
customuser.MyUser: (auth.E003) 'MyUser.username' must be unique because it is named as the 'USERNAME_FI ELD'

Try to specify email as username field with USERNAME_FIELD attribute:
class MyUser(AbstractUser):
username = models.CharField(max_length=30, unique=False)
USERNAME_FIELD = 'email'

class MyUser(AbstractUser):
username = models.CharField(max_length=30, unique=False)
email = models.EmailField(max_length=255, unique=True)
USERNAME_FIELD = 'email'

A non-unique username field is allowed if you use a custom authentication backend that can support it.
If you want to use django's default authentication backend you cannot make username non unique.
You will have to implement a class with get_user(user_id) and authenticate(request, **credentials) methods for a custom backend.
You can read it in the documentation here. https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#specifying-custom-user-model

Related

Can I remove existing fields or add some more fields in the default User DB in Django?, Also can i login using email instead of username?

I want to create a database for my project using the default Django database 'user' and I found that Django has a primary key username and some fields are not required, if I can add more fields to the existing DB 'user' that would be great...
I want to log in using email instead of username and change some fields to required. Also, can I add a field 'address and 'mobile'?
Iam using Django 3.5.2
I have tried adding new fields using the following but still couldn't find a way to change the primary key and required fields
forms.py ->
class CustomerUserForm(forms.ModelForm):
class Meta:
model=User #django default model
fields=['first_name','last_name','password','email','username']
widgets = {
'password': forms.PasswordInput()
}
class CustomerForm(forms.ModelForm):
class Meta:
model= models.CRegistration
fields=['address','mobile','profile_pic']
models.py ->
class CRegistration(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
profile_pic = models.ImageField(upload_to='profile_pic/CustomerProfilePic/', null=True, blank=True)
address = models.CharField(max_length=100)
mobile = models.CharField(max_length=20) #null=True
status = models.BooleanField(default=False)
Yes you can customise user table in django. Also you can authenticate with email
Here is the below link, this article explains exactly what you need. Refer the django documentation for more
Django custom user with email authentication

Django custom user with tuple as username

I have a solid level on Django, but can't find how to solve this one properly :
I created an API that will be used in multiple mobile projects. So I implemented an Application model that I pass when I log in.
I also created a custom user model :
class CustomUser(AbstractUser):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
username = None
email = models.EmailField('email address', unique=True)
application = models.ForeignKey(Application, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
class Meta:
unique_together = ('email', 'application')
I'm using djangorestframework-jwt. So I've an API call that needs an email, password and an Application (apikey as a string FYI) to get a token.
Everything is working fine, except that in this configuration, I'm not able to create another user with the same email but a different Application. Because my EmailField is my USERNAME_FIELD.
Is there any solution that would avoid me to rewrite everything ?
The best thing I have in mind is to add a field (for example a CharField) that would be unique (for example the combinaison of user.id + apikey) that would be filled automatically on creation. But then when I use ./manage.py createsuperuser, django would ask me to fill the field manually. Not a big deal but if you have a better/proper way I'd be glad !
How about use manytomany instead of foreignkey:
class CustomUser(AbstractUser):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
username = None
email = models.EmailField('email address', unique=True)
applications = models.ManyToManyField(Application, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
class Meta:
unique_together = (('email', 'application'),)

Django set_password no attribute

I'm trying to use the set_password() function but this error
'Member' object has no attribute 'set_password'
comes up when I use it. If I take out the set_password() function the password is stored in the database but without being hashed.
view.py
user = Member(username=u, password=p, email=e, security=s)
user.set_password(p)
user.save()
models.py
class Member(models.Model):
username = models.CharField(max_length=16,primary_key=True)
password = models.CharField(max_length=16)
email = models.CharField(max_length=325)
security = models.CharField(max_length=16)
profile = models.OneToOneField(Profile, null=True)
following = models.ManyToManyField("self", symmetrical=False)
from_member_id = models.CharField(max_length=16)
def __str__(self):
return self.username
The set_password function is not automatically provided by models.Model.
You have to define it by yourself or derive Member from django Usermodel
The documentation on providing your own user model is quite clear and comprehensive. Among other things, your model must be a subclass of AbstractBaseUser, which is what provides the set_password method.
Also note that 16 characters is not nearly long enough to store a hashed, salted password.
As the error message tells you, the method set_password is not defined.
Either you implement it yourself, or (better) create your Member model by subclassing django's AbrstactBaseUser:
class MyUser(AbstractBaseUser):
username = models.CharField(max_length=16,primary_key=True)
password = models.CharField(max_length=16)
email = models.CharField(max_length=325)
security = models.CharField(max_length=16)
profile = models.OneToOneField(Profile, null=True)
following = models.ManyToManyField("self", symmetrical=False)
from_member_id = models.CharField(max_length=16)
USERNAME_FIELD = 'username'
You can find more about custom user models in the django docs
Not sure if your doing this but it is probably easier to make the model with OneToOneField(User) and give it additional fields. You just need to remember to save in the new fields or the fields wont show up when u call.
Where you set the user_form=Member(request.POST)
user = user_form.save()
user.set_password(user.password)
profile = user.userprofile
profile.bio = request.POST['bio']
profile.save()

Django Registration Redux: how to change the unique identifier from username to email and use email as login

I'm using django-registration-redux in my project for user registration. It uses default User model which use username as the unique identifier.
Now we want to discard username and use email as the unique identifier.
And also we want to use email instead of username to login.
How to achieve this?
And is it possible to do it without changing the AUTH_USER_MODEL settings?
Because from the official doc it says
If you intend to set AUTH_USER_MODEL, you should set it before creating any migrations or running manage.py migrate for the first time.
You can override registration form like this
from registration.forms import RegistrationForm
class MyRegForm(RegistrationForm):
username = forms.CharField(max_length=254, required=False, widget=forms.HiddenInput())
def clean_email(self):
email = self.cleaned_data['email']
self.cleaned_data['username'] = email
return email
And then add this to settings file (read this link for details)
REGISTRATION_FORM = 'app.forms.MyRegForm'
This will set the email to username field as well and then everything will work as email is now the username.
The only problem is that username field has a max lenght of 30 in DB. So emails longer than 30 chars will raise DB exception. To solve that override the user model (read this for details).
The easiest way to achieve this is to made your own custom User Model.
This is the example
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
Then, you need to set the User Model in your Django settings. https://docs.djangoproject.com/en/1.8/ref/settings/#auth-user-model
You will want to use AbstractBaseUser. Docs are here:
https://docs.djangoproject.com/en/1.8/topics/auth/customizing/
Good luck!

Django custom user model with unique_together on the email

I'm trying to create a custom User model in my Django app, the problem is I get an error saying email must be unique (fair enough!), however, I need email and company together to be unique, as I may have the same email but registered to a different company.
I get the following error:
ERRORS:
site.SiteUser: (auth.E003) 'SiteUser.email' must be unique because it is named as the 'USERNAME_FIELD'.
Here is my model:
class SiteUser(models.Model):
company = models.ForeignKey(Company)
email = models.EmailField(max_length=254)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now=False, auto_now_add=True)
objects = SiteUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
unique_together = ('company', 'email',)
You're missing the unique=True in your email field definition.
The filed that is used in the USERNAME_FIELD should have this argument as explained in the django doc on USERNAME_FIELD.
It should be like this:
email = models.EmailField(max_length=254, unique=True)
Add auth.E003 to the SILENCED_SYSTEM_CHECKS setting. This will allow manage.py to run. And I think you should add W004 warning to this list too:
SILENCED_SYSTEM_CHECKS = ['auth.E003', 'auth.W004']

Categories