Override django user with AUTH_USER_MODEL - python

I have override the default User model in my app with AUTH_USER_MODEL.
Here is the user model I want to use in my app, which is tied closely to a legacy database:
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
name = models.CharField(max_length=128, blank=True)
email = models.EmailField(unique=True)
password = models.CharField(max_length=128)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
normalized_email = models.EmailField(unique=True)
However, django complains that fields such as first_name, last_name, etc. are not provided. Is there a way to remove some of the existing fields in the User model? Or does specifying a custom user model only allow you to add additional fields on top of that? Is there a simple way to delete them, or do I basically have to add those fields (and ignore them) to our existing database in order to be able to use django with it?

AbstractUser is for when you want to add additional fields to Django's defaults. Use AbstractBaseUser if you don't want all those fields.

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: use a Foreignkey relationship for custom user model

I am writing a webapp where I want to have a general Person table to uniquely identify any person interacting with the website, e.g. to be able to comply to GDPR requests.
Some Persons will should also be Users in the authentication sense.
I'd like to use Person.email for the username.
However, I cannot manage to make authentication / admin interface work.
Simplified models:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
class Person(models.Model):
name = models.CharField(max_length=255, blank=False)
email = models.EmailField(blank=False, unique=True)
class User(AbstractBaseUser, PermissionsMixin):
person = models.OneToOneField(Person, on_delete=models.PROTECT)
USERNAME_FIELD = ...# what to put here?
I found a very old Django issue that seems related:
https://code.djangoproject.com/ticket/21832
Any idea, how to make this work with a foreign key to hold the basic user information?
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
Here you go for correct way of achieving this
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
USERNAME_FIELD = ['email'] # It's mean you can login with your email
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Note: If you use AbstractBaseUser models, then you have to write custom model manager.
To avoid writing custom models manager, you should use AbstractUser
class User(AbstractUser):
pass
# here all the required fields like email, name etc item
You can create Person record for the user when a user records creating using django signal:
https://docs.djangoproject.com/en/3.2/topics/signals/

How to have multiple AUTH_USER_MODEL in django

I have two different app that has separate models that inherits from AbstractionBaseUser like below
# in doctor/models.py
...
class Patient(AbstractBaseUser):
email = models.EmailField(blank=True, unique=True)
phone_number = models.IntegerField(blank=False, unique=True)
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELD = ['phone_number', 'email']
...
# in Patient/models.py
...
class Patient(AbstractBaseUser):
email = models.EmailField(blank=True, unique=True)
phone_number = models.IntegerField(blank=False, unique=True)
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELD = ['phone_number', 'email']
...
Both models have different fields
# in settings.py
AUTH_USER_MODEL = [
'doctor.Doctor',
'patient.Patient'
]
I tried to do this but in making migration it tells me that it must be a single model
AssertionError: ForeignKey(['doctor.Doctor', 'patient.Patient']) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'
I read docs but I couldn't find any help
How can I fix this and how can I have multiple AUTH_USER_MODEL
how can I have multiple AUTH_USER_MODEL.
You don't. There is one user model. It would also make all procedures more complicated. What if a the same email address occurs in both the Doctor and Patient model? Then how would you log in such person?
You can however make multiple extra models with a ForeignKey to the user model. We can for example use the default user model:
# settings.py
# …
AUTH_USER_MODEL = 'auth.User'
# …
You can of course also specify a basic user model yourself. But it should be one user model.
Then both the Doctor and Patient model can have a one-to-one relation to the User model:
from django.db import models
from django.conf import settings
class Doctor(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
# … extra doctor fields …
as well as a patient:
from django.db import models
from django.conf import settings
class Patient(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
# … extra patient fields …
You can then check for a user if it is a doctor by accessing the .doctor attribute:
from django.contrib.auth.decorators import login_required
#login_required
def some_view(request):
try:
doctor = request.user.doctor
except AttributeError:
# … user is not a doctor …
pass
pass
This also allows that a User is both a Doctor and a Patient for example. This may look odd at first. But later it is possible that you introduce more roles, and it is not impossible that the same user is assigned multiple roles, for example doctor and supervisor of a department.

How to override max length of username in Django by creating a custom model

I have a problem. I'm using Django 1.7, and have already made a custom user model, that inherits Django's abstract user like this:
class CustomUser(AbstractUser, BaseModel):
Now they say in here Django-ticket, that I could avoid the problem of username's max_length being 30, by creating a custom user. Well, I already have a custom user, so it should be easy right? How I tried to do it was:
class CustomUser(AbstractUser, BaseModel):
username = models.CharField(max_length=70, unique=True, db_index=True)
Now when I try to make migrations for changing this field, it results in an error: django.core.exceptions.FieldError: Local field 'username' in class 'CustomUser' clashes with field of similar name from base class 'AbstractUser'
What am I doing wrong? How could I solve this problem? I have data that should be migrated, so I cannot empty database.
Dont try to override username field. Just
class CustomUser(AbstractUser, BaseModel):
#here goes other fields
CustomUser._meta.get_field('username').max_length = 70
But I highly recommend to inherit from AbstractBaseUser instead.
If you want it to be more flexible inherit from AbstractBaseUser instead, you will be able to specify your own username field that way, e.g.
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
date_joined = models.DateTimeField(
verbose_name=_('date created'),
auto_created=True,
default=timezone.now
)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#specifying-a-custom-user-model
As I understood you can't override any Django ORM model's attribute, nor from AbstractUser, nor from PermissionsMixin classes. So, If you have your own approach to Permissions, Groups(Roles), even if you want another attribute name than user_permissions or groups, then you should inherit from AbstractBaseUser, doing a lot of copy-paste from AbstractUser and inherit your Permission and Group models from django.db.models.Model class as #levi and #Hedde van der Heide suggested.

Extending Django User model with django-allauth

I'm using django-allauth and I want to be able to add new field to my User model.
What's the best way to do this as of you ?
I use userena. But I am sure that it will look almost the same ;)
class UserProfile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True)
city = models.CharField(max_length=32, blank=True, null=True)
in settings.py:
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
See the docs Storing additional information about users, Make a model with OneToOneField relation to User.
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")

Categories