Where is django.contrib.auth.User defined in Django source code - django

In Django official guide, it reads:
Inside this django.contrib.auth model, there is a User class, who has following attributes (username, password, email, first_name, last_name).
When I check the source code in github, I did not find this definition in django.contrib.auth.
I can only see class AbstractBaseUser(models.Model): in django/contrib/auth/base_user.py on this link, and class User(AbstractUser): in django/contrib/auth/models.py in this webpage.
Q1: what does class models.User mean in above official document, it means User is a class under models.py ?
Q2: if above is right, then where User class get attributes such as username, email etc?

Q1: what does class models.User mean in above official document, it means User is a class under models.py?
In Django one refers to a model with the app_name.ModelName. So if you specify a model, this is implemented in the app_name/models.py, but since models are defined in the models.py file, it makes no sense to include that in the name of the model.
For example the default for the AUTH_USER_MODEL setting [Django-doc] is auth.User, since the name of the app is auth, and the name of the model is User.
Q2: if above is right, then where User class get attributes such as username, email etc?
Through inheritance. Indeed if we look at the source code of the models.py file [GitHub], we see:
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this
model.
Username and password are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
and the AbstractUser model [GitHub] defines the fields for username, email, etc.:
class AbstractUser(AbstractBaseUser, PermissionsMixin):
# …
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=150, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
# …
AbstractUser is an abstract model. This means that Django does not create a table for it. Models that inherit from an abstract table will thus inherit fields, methods, etc. and these fields will then be defined on the model that inherits from AbstractUser.

Related

How can I make a user out of a model in Django?

I'm currently developing a web-application for managing driving licenses as a web development homework assignment. Instead of just storing information on every driver as a model I want to make a user for each driver. What is the easiest way to do so? What am I doing wrong?
I updated a car owner model so that it is now inherited from djangdo Abstract User.
# models.py
class Car_owner(AbstractUser):
id_owner = models.IntegerField(primary_key=True)
last_name = models.CharField(max_length=30, null=False)
first_name = models.CharField(max_length=30, null=False)
birth_date = models.DateField(null=True)
passport = models.IntegerField(null=True, blank=True)
address = models.CharField(max_length=50, null=True, blank=True)
nationality = models.CharField(max_length=15, null=True, blank=True)
# username = models.CharField(max_length=16, unique=True, default=uuid4)
# password = models.CharField(max_length=16, default='password')
I also have forms.py file:
from django import forms
from project_first_app.models import Car_owner
class CreateOwner(forms.ModelForm):
class Meta:
model = Car_owner
fields = ['id_owner', 'last_name', 'first_name', 'birth_date', 'passport', 'address', 'nationality']
But when migrating I get the following issue:
UNIQUE constraint failed: new__project_first_app_car_owner.username
In migrations files I have:
migrations.AddField(
model_name='car_owner',
name='username',
field=models.CharField(default=uuid.uuid4, max_length=16, unique=True),
),
and then:
migrations.AlterField(
model_name='car_owner',
name='username',
field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
),
Those are automatically generated.
You have commented username and password in your model, why ?
Password field already exists in the abstractbaseuser, so comment it does not remove it. The abstract model user of Django need a unique information for authenticating user. You can use a Username or an Email.
For using the email instead of username, you can define USERNAME_FIELD = "email" in your class. But you have to define a field email, or you keep username field and add it to fields ModelForm.
There is a constraint on the username field (or email field), so you have to define it for each Car_owner you want to create (it is for authenticating purpose).
your field id_owner is useless, Django create automatically a field called id in each model which is the primary key.
so for resolving your problem easily, add username in fields list of your Form for beginning.

Handling JWT Authentication and Soft Deleted Users in Django Rest Framework

I'm trying to make a username available once a user deletes their account. By default the username is unique meaning the username won't be available even after the account is soft deleted.
This is, by default, the setup that comes with django out of the box.
class CustomUser(AbstractUser):
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only.'),
validators=[UnicodeUsernameValidator()],
error_messages={
'unique': _("A user with that username already exists."),
},
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
is_active is used here to mark a model as deleted.
So that I can be able to take advantage of UniqueConstraint and add a condition, I have to drop the uniqueness of the username.
class CustomUser(AbstractUser):
username = models.CharField(
_('username'),
max_length=150,
unique=False,
help_text=_('Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only.'),
validators=[UnicodeUsernameValidator()],
error_messages={
'unique': _("A user with that username already exists."),
},
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['username'],
name='active_username_constraint',
condition=models.Q(is_active=True)
)
]
This works for registrations. After a user has deleted their account, the username can be re-used during registration. However, when a user logs in, the following error is raised.
MultipleObjectsReturned at /api/vdev/login/
get() returned more than one CustomUser -- it returned 2!
I'm trying to find out a way to check if a user is_active as part of the authentication process. Is there a way this can be done?
I'm guessing the error is raised when the authenticate is being called from the UserModel. Looking at the source code, the method calls get_by_natural_key from the user manager. Examining the source code for this method shows us where we need to make the change.
Hence, what you'll probably have to do is to create a custom user manager, inheriting from BaseUserManager and overriding get_by_natural_key.
class MyUserManager(BaseUserManager):
...
def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD: username, "is_active": True})
Then in your custom user model, set your manager to this custom user manager:
class CustomUser(AbstractUser):
...
objects = MyUserManager()

Add to auth_user [duplicate]

This question already has answers here:
Extending the User model with custom fields in Django
(16 answers)
Closed 2 years ago.
I have this program that gets most of its data from the auth_user table one the django database. I don’t know how to add a new column to it and make it actually work since it doesn’t recognize it when I do. Does anybody know how you would add a column that can be used in auth_user table in the default django database.
I think this is a part that well documented on Django's documentation site. I guess you are trying to create custom user model. But I recommend you to extend user model. Extending default user model will provide you more flexibility. I hope these two links will enough. If not, please comment me about missing parts to cover.
You can override default user model or extend user model with OneToOneField relation to satisfy this requirement.
1. I'll show you how to do custom User Model.
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from core.util.validators import UnicodeUsernameValidator
from .manager import UserManager
class User(AbstractBaseUser, PermissionsMixin):
"""
Username, Email and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_(
'150 characters or fewer. Letters, digits and #/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
null=True,
default=None
)
email = models.EmailField(
_('email address'),
blank=False,
unique=True,
error_messages={
'unique': _("A user with that email address already exists."),
},
)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
permissions = (
('user_permission', "User Permission"),
('admin_permission', "Admin Permission"),
)
This is like a copy of what they have in their User model. here, You can add new fields.
Make sure to register this in settings.py
AUTH_USER_MODEL = 'userapp.User'
you can access extra_fields like
user.extra_field
2. I'll show you how to extend using OneToOneField.
from django.contrib.auth import get_user_model
class Profile(models.Model):
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE)
...
# Extra fields Here
then you can access the extra fields as
user.profile.extra_field

Best practices for extending Custom User Model in django

I have a Custom User model in my app
class User(AbstractBaseUser, PermissionsMixin):
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
email = models.EmailField(_('email address'), db_index=True, unique=True)
and this AUTH_USER_MODEL = 'users.User' in my settings file.
Now I want to create a model on the top of this custom user model(User), lets call it Agent, this model will have three columns:
user_uuid #Foreign Key Refernce(OnetoOne) to the Custom User Model
uuid # unique identifier for Agent model
scope # CharField specific to Agent model
What is the best way to do that?
While there is no best practice, it all depends on what you are doing, the most likely to work method is a type field specifying Agent and a one-to-one table (docs) for extra fields.
It'll be up to you to create the records as-needed. There isn't anything special about what you are doing just because it is a user.
class AgentDetails(Model):
user = OneToOneField(User, primary_key=True, on_delete=CASCADE)
...
A more complete user model would look something like this:
class User(AbstractBaseUser, PermissionsMixin):
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ["name"]
email = EmailField(unique=True, db_index=True)
name = CharField(max_length=100)
type = ChoiceField(choices=[('user','User'),('agent','Agent')])
is_staff = models.BooleanField(default=False, help_text='If the user can log into this admin site.')
is_active = models.BooleanField(default=True, help_text='If the user is active, instead of deleting')
created_at = models.DateTimeField('Date Joined', default=timezone.now)
objects = MyUserManager() #
In addition, you are probably going to need to add:
Custom admin page
Custom UserManager
You can derive one table from an abstract base, but this will generate 1 table for each user type which will not work with the standard authentication. For info, see Django's Model Inheritance.
class User(Model):
email = EmailField()
class Meta:
abstract = True
class Agent(User): # generates table 1
extra_field = CharField()
class Standard(User): # generates table 2
extra_field = CharField()
If the user model you have given is complete, then I don't think it will work with the default django infrastructure. From your question its not clear if you need help on that.

How to create model containing subset of User model's fields in Django

How can I create OrderUser model containing subfields of User model that are desired:
first_name
last_name
email
I want to avoid manually copying fields' structure from django.contrib.auth.models AbstractUser like
class OrderUser(models.Model):
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), blank=True)
I wonder if there is any way to write something like this:
class OrderUser(models.Model):
first_name = User.fields.first_name
last_name = User.fields.last_name
email = User.fields.email
Usually, if I want two models to have the same fields, I use Abstract Model inheritance.
But inheriting from AbstractUser leads to many unnecessary fields like username, is_staff, is_active and so on.
Ok, my bad, I finally found an answer to my own question, maybe it will be helpful for someone else.
The _meta property worked for me:
class OrderUser(models.Model):
first_name = User._meta.get_field_by_name('first_name')[0]
last_name = User._meta.get_field_by_name('last_name')[0]
email = User._meta.get_field_by_name('email')[0]
More discussion about _meta:
Get model's fields in Django
How to introspect django model fields?