<p>What's the best way to extend the User model (bundled with Django's authentication app) with custom fields? I would also possibly like to use the email as the username (for authentication purposes).</p>

<p>I've already seen a <a href="http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/" rel="noreferrer">few</a> <a href="http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/" rel="noreferrer">ways</a> to do it, but can't decide on which one is the best.</p>

[{'answer_id': 44133, 'author': 'Dmitry Mukhin', 'author_id': 3448, 'author_profile': 'https://Stackoverflow.com/users/3448', 'pm_score': 6, 'selected': False, 'text': '<p>There is an official recommendation on <a href="http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users" rel="noreferrer">storing additional information about users</a>.\nThe Django Book also discusses this problem in section <a href="http://www.djangobook.com/en/1.0/chapter12/#cn222" rel="noreferrer">Profiles</a>.</p>\n'}, {'answer_id': 44178, 'author': 'Ryan Duffield', 'author_id': 2696, 'author_profile': 'https://Stackoverflow.com/users/2696', 'pm_score': 9, 'selected': True, 'text': '<p>The least painful and indeed Django-recommended way of doing this is through a <code>OneToOneField(User)</code> property.</p>\n<blockquote>\n<h2><a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model" rel="noreferrer">Extending the existing User model</a></h2>\n<p>…</p>\n<p>If you wish to store information related to <code>User</code>, you can use a <a href="https://docs.djangoproject.com/en/dev/ref/models/fields/#ref-onetoone" rel="noreferrer">one-to-one relationship</a> to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.</p>\n</blockquote>\n<p>That said, extending <code>django.contrib.auth.models.User</code> and supplanting it also works...</p>\n<blockquote>\n<h2><a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model" rel="noreferrer">Substituting a custom User model</a></h2>\n<p>Some kinds of projects may have authentication requirements for which Django’s built-in <code>User</code> model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.</p>\n<p><em>[Ed: <strong>Two warnings and a notification follow</strong>, mentioning that this is <strong>pretty drastic</strong>.]</em></p>\n</blockquote>\n<p>I would definitely stay away from changing the actual User class in your Django source tree and/or copying and altering the auth module.</p>\n'}, {'answer_id': 705389, 'author': 'Rama Vadakattu', 'author_id': 270442, 'author_profile': 'https://Stackoverflow.com/users/270442', 'pm_score': 5, 'selected': False, 'text': '<p>The below one is another approach to extend an User.\nI feel it is more clear,easy,readable  then above two approaches.</p>\n\n<p><a href="http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/" rel="noreferrer">http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/</a></p>\n\n<p>Using above approach:</p>\n\n<ol>\n<li>you don\'t need to use\n<em>user.get_profile().newattribute</em> to access the additional information\nrelated to the user</li>\n<li>you can just directly access\nadditional new attributes via \n<em>user.newattribute</em></li>\n</ol>\n'}, {'answer_id': 965883, 'author': 'Raisins', 'author_id': 75803, 'author_profile': 'https://Stackoverflow.com/users/75803', 'pm_score': 8, 'selected': False, 'text': '<p><strong>Note: this answer is deprecated. see other answers if you are using Django 1.7 or later.</strong></p>\n\n<p>This is how I do it.</p>\n\n<pre><code>#in models.py\nfrom django.contrib.auth.models import User\nfrom django.db.models.signals import post_save\n\nclass UserProfile(models.Model):  \n    user = models.OneToOneField(User)  \n    #other fields here\n\n    def __str__(self):  \n          return "%s\'s profile" % self.user  \n\ndef create_user_profile(sender, instance, created, **kwargs):  \n    if created:  \n       profile, created = UserProfile.objects.get_or_create(user=instance)  \n\npost_save.connect(create_user_profile, sender=User) \n\n#in settings.py\nAUTH_PROFILE_MODULE = \'YOURAPP.UserProfile\'\n</code></pre>\n\n<p>This will create a userprofile each time a user is saved if it is created. \nYou can then use</p>\n\n<pre><code>  user.get_profile().whatever\n</code></pre>\n\n<p>Here is some more info from the docs</p>\n\n<p><a href="http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users" rel="noreferrer">http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users</a></p>\n\n<p><strong>Update:</strong> Please note that <code>AUTH_PROFILE_MODULE</code> is deprecated since v1.5: <a href="https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module" rel="noreferrer">https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module</a></p>\n'}, {'answer_id': 12648124, 'author': 'Ondrej Slinták', 'author_id': 206720, 'author_profile': 'https://Stackoverflow.com/users/206720', 'pm_score': 8, 'selected': False, 'text': '<p>Well, some time passed since 2008 and it\'s time for some fresh answer. Since Django 1.5 you will be able to create custom User class. Actually, at the time I\'m writing this, it\'s already merged into master, so you can try it out.</p>\n\n<p>There\'s some information about it in <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#a-full-example">docs</a> or if you want to dig deeper into it, in <a href="https://github.com/django/django/commit/70a0de37d132e5f1514fb939875f69649f103124">this commit</a>.</p>\n\n<p>All you have to do is add <code>AUTH_USER_MODEL</code> to settings with path to custom user class, which extends either <code>AbstractBaseUser</code> (more customizable version) or <code>AbstractUser</code> (more or less old User class you can extend).</p>\n\n<p>For people that are lazy to click, here\'s code example (taken from <a href="https://docs.djangoproject.com/en/dev/topics/auth/#a-full-example">docs</a>):</p>\n\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import (\n    BaseUserManager, AbstractBaseUser\n)\n\n\nclass MyUserManager(BaseUserManager):\n    def create_user(self, email, date_of_birth, password=None):\n        """\n        Creates and saves a User with the given email, date of\n        birth and password.\n        """\n        if not email:\n            raise ValueError(\'Users must have an email address\')\n\n        user = self.model(\n            email=MyUserManager.normalize_email(email),\n            date_of_birth=date_of_birth,\n        )\n\n        user.set_password(password)\n        user.save(using=self._db)\n        return user\n\n    def create_superuser(self, username, date_of_birth, password):\n        """\n        Creates and saves a superuser with the given email, date of\n        birth and password.\n        """\n        u = self.create_user(username,\n                        password=password,\n                        date_of_birth=date_of_birth\n                    )\n        u.is_admin = True\n        u.save(using=self._db)\n        return u\n\n\nclass MyUser(AbstractBaseUser):\n    email = models.EmailField(\n                        verbose_name=\'email address\',\n                        max_length=255,\n                        unique=True,\n                    )\n    date_of_birth = models.DateField()\n    is_active = models.BooleanField(default=True)\n    is_admin = models.BooleanField(default=False)\n\n    objects = MyUserManager()\n\n    USERNAME_FIELD = \'email\'\n    REQUIRED_FIELDS = [\'date_of_birth\']\n\n    def get_full_name(self):\n        # The user is identified by their email address\n        return self.email\n\n    def get_short_name(self):\n        # The user is identified by their email address\n        return self.email\n\n    def __unicode__(self):\n        return self.email\n\n    def has_perm(self, perm, obj=None):\n        "Does the user have a specific permission?"\n        # Simplest possible answer: Yes, always\n        return True\n\n    def has_module_perms(self, app_label):\n        "Does the user have permissions to view the app `app_label`?"\n        # Simplest possible answer: Yes, always\n        return True\n\n    @property\n    def is_staff(self):\n        "Is the user a member of staff?"\n        # Simplest possible answer: All admins are staff\n        return self.is_admin\n</code></pre>\n'}, {'answer_id': 15358142, 'author': 'chhantyal', 'author_id': 843463, 'author_profile': 'https://Stackoverflow.com/users/843463', 'pm_score': 2, 'selected': False, 'text': '<p>New in Django 1.5, now you can create your own Custom User Model (which seems to be good thing to do in above case). Refer to <a href="https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model" rel="nofollow">\'Customizing authentication in Django\'</a></p>\n\n<p>Probably the coolest new feature on 1.5 release.</p>\n'}, {'answer_id': 16125609, 'author': 'Riccardo Galli', 'author_id': 210090, 'author_profile': 'https://Stackoverflow.com/users/210090', 'pm_score': 6, 'selected': False, 'text': '<p>Since Django 1.5 you may easily extend the user model and keep a single table on the database.</p>\n\n<pre><code>from django.contrib.auth.models import AbstractUser\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\n\nclass UserProfile(AbstractUser):\n    age = models.PositiveIntegerField(_("age"))\n</code></pre>\n\n<p>You must also configure it as current user class in your settings file</p>\n\n<pre><code># supposing you put it in apps/profiles/models.py\nAUTH_USER_MODEL = "profiles.UserProfile"\n</code></pre>\n\n<p>If you want to add a lot of users\' preferences the OneToOneField option may be a better choice thought.</p>\n\n<p>A note for people developing third party libraries: if you need to access the user class remember that people can change it. Use the official helper to get the right class</p>\n\n<pre><code>from django.contrib.auth import get_user_model\n\nUser = get_user_model()\n</code></pre>\n'}, {'answer_id': 36592330, 'author': 'Massimo Variolo', 'author_id': 752102, 'author_profile': 'https://Stackoverflow.com/users/752102', 'pm_score': 4, 'selected': False, 'text': '<p><strong>Extending Django User Model (UserProfile) like a Pro</strong></p>\n<p>I\'ve found this very useful: <a href="https://blog.khophi.co/extending-django-user-model-userprofile-like-a-pro/" rel="nofollow noreferrer">link</a></p>\n<p><strong>An extract:</strong></p>\n<pre><code>from django.contrib.auth.models import User\n\nclass Employee(models.Model):\n    user = models.OneToOneField(User)\n    department = models.CharField(max_length=100)\n\n&gt;&gt;&gt; u = User.objects.get(username=\'fsmith\')\n&gt;&gt;&gt; freds_department = u.employee.department\n</code></pre>\n'}, {'answer_id': 38024560, 'author': 'Atul Yadav', 'author_id': 6507549, 'author_profile': 'https://Stackoverflow.com/users/6507549', 'pm_score': 4, 'selected': False, 'text': '<p>You can Simply extend user profile by creating a new entry each time when a user is created by using Django post save signals</p>\n\n<h1>models.py</h1>\n\n<pre><code>from django.db.models.signals import *\nfrom __future__ import unicode_literals\n\nclass UserProfile(models.Model):\n\n    user_name = models.OneToOneField(User, related_name=\'profile\')\n    city = models.CharField(max_length=100, null=True)\n\n    def __unicode__(self):  # __str__\n        return unicode(self.user_name)\n\ndef create_user_profile(sender, instance, created, **kwargs):\n    if created:\n        userProfile.objects.create(user_name=instance)\n\npost_save.connect(create_user_profile, sender=User)\n</code></pre>\n\n<p>This will automatically create an employee instance when a new user is created.</p>\n\n<p>If you wish to extend user model and want to add further information while creating a user you can use django-betterforms (<a href="http://django-betterforms.readthedocs.io/en/latest/multiform.html" rel="noreferrer">http://django-betterforms.readthedocs.io/en/latest/multiform.html</a>). This will create a user add form with all fields defined in the UserProfile model.</p>\n\n<h1>models.py</h1>\n\n<pre><code>from django.db.models.signals import *\nfrom __future__ import unicode_literals\n\nclass UserProfile(models.Model):\n\n    user_name = models.OneToOneField(User)\n    city = models.CharField(max_length=100)\n\n    def __unicode__(self):  # __str__\n        return unicode(self.user_name)\n</code></pre>\n\n<h1>forms.py</h1>\n\n<pre><code>from django import forms\nfrom django.forms import ModelForm\nfrom betterforms.multiform import MultiModelForm\nfrom django.contrib.auth.forms import UserCreationForm\nfrom .models import *\n\nclass ProfileForm(ModelForm):\n\n    class Meta:\n        model = Employee\n        exclude = (\'user_name\',)\n\n\nclass addUserMultiForm(MultiModelForm):\n    form_classes = {\n        \'user\':UserCreationForm,\n        \'profile\':ProfileForm,\n    }\n</code></pre>\n\n<h1>views.py</h1>\n\n<pre><code>from django.shortcuts import redirect\nfrom .models import *\nfrom .forms import *\nfrom django.views.generic import CreateView\n\nclass AddUser(CreateView):\n    form_class = AddUserMultiForm\n    template_name = "add-user.html"\n    success_url = \'/your-url-after-user-created\'\n\n    def form_valid(self, form):\n        user = form[\'user\'].save()\n        profile = form[\'profile\'].save(commit=False)\n        profile.user_name = User.objects.get(username= user.username)\n        profile.save()\n        return redirect(self.success_url)\n</code></pre>\n\n<h1>addUser.html</h1>\n\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html lang="en"&gt;\n    &lt;head&gt;\n        &lt;meta charset="UTF-8"&gt;\n        &lt;title&gt;Title&lt;/title&gt;\n    &lt;/head&gt;\n    &lt;body&gt;\n        &lt;form action="." method="post"&gt;\n            {% csrf_token %}\n            {{ form }}     \n            &lt;button type="submit"&gt;Add&lt;/button&gt;\n        &lt;/form&gt;\n     &lt;/body&gt;\n&lt;/html&gt;\n</code></pre>\n\n<h1>urls.py</h1>\n\n<pre><code>from django.conf.urls import url, include\nfrom appName.views import *\nurlpatterns = [\n    url(r\'^add-user/$\', AddUser.as_view(), name=\'add-user\'),\n]\n</code></pre>\n'}, {'answer_id': 51511108, 'author': 'Milad Khodabandehloo', 'author_id': 9083861, 'author_profile': 'https://Stackoverflow.com/users/9083861', 'pm_score': 2, 'selected': False, 'text': '<p>This is what i do and it\'s in my opinion simplest way to do this. define an object manager for your new customized model then define your model.</p>\n\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import PermissionsMixin, AbstractBaseUser, BaseUserManager\n\nclass User_manager(BaseUserManager):\n    def create_user(self, username, email, gender, nickname, password):\n        email = self.normalize_email(email)\n        user = self.model(username=username, email=email, gender=gender, nickname=nickname)\n        user.set_password(password)\n        user.save(using=self.db)\n        return user\n\n    def create_superuser(self, username, email, gender, password, nickname=None):\n        user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)\n        user.is_superuser = True\n        user.is_staff = True\n        user.save()\n        return user\n\n\n\n  class User(PermissionsMixin, AbstractBaseUser):\n    username = models.CharField(max_length=32, unique=True, )\n    email = models.EmailField(max_length=32)\n    gender_choices = [("M", "Male"), ("F", "Female"), ("O", "Others")]\n    gender = models.CharField(choices=gender_choices, default="M", max_length=1)\n    nickname = models.CharField(max_length=32, blank=True, null=True)\n\n    is_active = models.BooleanField(default=True)\n    is_staff = models.BooleanField(default=False)\n    REQUIRED_FIELDS = ["email", "gender"]\n    USERNAME_FIELD = "username"\n    objects = User_manager()\n\n    def __str__(self):\n        return self.username\n</code></pre>\n\n<p>Dont forget to add this line of code in your <code>settings.py</code>:</p>\n\n<pre><code>AUTH_USER_MODEL = \'YourApp.User\'\n</code></pre>\n\n<p>This is what i do and it always works.</p>\n'}, {'answer_id': 58921445, 'author': 'David Torrey', 'author_id': 1462056, 'author_profile': 'https://Stackoverflow.com/users/1462056', 'pm_score': 0, 'selected': False, 'text': '<p>Currently as of Django 2.2, the recommended way when starting a new project is to create a custom user model that inherits from AbstractUser, then point AUTH_USER_MODEL to the model.</p>\n\n<p>Source: <a href="https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project" rel="nofollow noreferrer">https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project</a></p>\n'}, {'answer_id': 60355460, 'author': 'NeerajSahani', 'author_id': 12270394, 'author_profile': 'https://Stackoverflow.com/users/12270394', 'pm_score': 1, 'selected': False, 'text': "<p>Simple and effective approach is\nmodels.py</p>\n\n<pre><code>from django.contrib.auth.models import User\nclass CustomUser(User):\n     profile_pic = models.ImageField(upload_to='...')\n     other_field = models.CharField()\n</code></pre>\n"}, {'answer_id': 64312498, 'author': 'Shahriar.M', 'author_id': 3777814, 'author_profile': 'https://Stackoverflow.com/users/3777814', 'pm_score': 2, 'selected': False, 'text': "<p>It's too late, but my answer is for those who search for a solution with a recent version of Django.</p>\n<p><code>models.py</code>:</p>\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import User\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\n\n\nclass Profile(models.Model):\n    user = models.OneToOneField(User, on_delete=models.CASCADE)\n    extra_Field_1 = models.CharField(max_length=25, blank=True)\n    extra_Field_2 = models.CharField(max_length=25, blank=True)\n\n\n@receiver(post_save, sender=User)\ndef create_user_profile(sender, instance, created, **kwargs):\n    if created:\n        Profile.objects.create(user=instance)\n\n@receiver(post_save, sender=User)\ndef save_user_profile(sender, instance, **kwargs):\n    instance.profile.save()\n</code></pre>\n<p>you can use it in templates like this:</p>\n<pre><code>&lt;h2&gt;{{ user.get_full_name }}&lt;/h2&gt;\n&lt;ul&gt;\n  &lt;li&gt;Username: {{ user.username }}&lt;/li&gt;\n  &lt;li&gt;Location: {{ user.profile.extra_Field_1 }}&lt;/li&gt;\n  &lt;li&gt;Birth Date: {{ user.profile.extra_Field_2 }}&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n<p>and in <code>views.py</code> like this:</p>\n<pre><code>def update_profile(request, user_id):\n    user = User.objects.get(pk=user_id)\n    user.profile.extra_Field_1 = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit...'\n    user.save()\n</code></pre>\n"}, {'answer_id': 65976535, 'author': 'Ajay Lingayat', 'author_id': 12132509, 'author_profile': 'https://Stackoverflow.com/users/12132509', 'pm_score': 0, 'selected': False, 'text': "<p>Try this:</p>\n<p>Create a model called <code>Profile</code> and reference the user with a <code>OneToOneField</code> and provide an option of <code>related_name</code>.</p>\n<p><strong>models.py</strong></p>\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import *\nfrom django.dispatch import receiver\nfrom django.db.models.signals import post_save\n\nclass Profile(models.Model):\n    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')\n\n    def __str__(self):\n        return self.user.username\n\n@receiver(post_save, sender=User)\ndef create_profile(sender, instance, created, **kwargs):\n    try:\n        if created:\n            Profile.objects.create(user=instance).save()\n    except Exception as err:\n        print('Error creating user profile!')\n</code></pre>\n<p>Now to directly access the profile using a <code>User</code> object you can use the <code>related_name</code>.</p>\n<p><strong>views.py</strong></p>\n<pre><code>from django.http import HttpResponse\n\ndef home(request):\n    profile = f'profile of {request.user.user_profile}'\n    return HttpResponse(profile)\n</code></pre>\n"}, {'answer_id': 67204210, 'author': 'Alphonse Prakash', 'author_id': 13344453, 'author_profile': 'https://Stackoverflow.com/users/13344453', 'pm_score': 3, 'selected': False, 'text': '<p>It\'s very easy in Django version 3.0+ (<strong>If you are NOT in the middle of a project</strong>):</p>\n<p>In <strong>models.py</strong></p>\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import AbstractUser\n\nclass CustomUser(AbstractUser):\n    extra_field=models.CharField(max_length=40)\n</code></pre>\n<p>In <strong>settings.py</strong></p>\n<p>First, register your new app and then below <strong>AUTH_PASSWORD_VALIDATORS</strong>\nadd</p>\n<pre><code>AUTH_USER_MODEL =\'users.CustomUser\'\n</code></pre>\n<p>Finally, register your model in the admin, run makemigrations and migrate, and it will be completed successfully.</p>\n<p>Official doc: <a href="https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#substituting-a-custom-user-model" rel="nofollow noreferrer">https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#substituting-a-custom-user-model</a></p>\n'}, {'answer_id': 72434745, 'author': 'Mahammadhusain kadiwala', 'author_id': 19205926, 'author_profile': 'https://Stackoverflow.com/users/19205926', 'pm_score': 2, 'selected': False, 'text': '<p>Here I tried to explain how to extend Django\'s Default user model with extra fields\nIt\'s very simple just do it.</p>\n<p>Django allows extending the default user model with <strong>AbstractUser</strong></p>\n<p><strong>Note:-</strong> first create an extra field model which you want to add in user model then run the command <strong>python manage.py makemigrations</strong> and <strong>python manage.py migrate</strong></p>\n<p>first run ---&gt; <strong>python manage.py makemigrations</strong> then</p>\n<p>second run <strong>python manage.py migrate</strong></p>\n<p>Step:- create a model with extra fields which you want to add in Django default user model (in my case I created <strong>CustomUser</strong></p>\n<p><strong>model.py</strong></p>\n<pre><code>from django.db import models\nfrom django.contrib.auth.models import AbstractUser\n# Create your models here.\n\n\nclass CustomUser(AbstractUser):\n    mobile_no = models.IntegerField(blank=True,null=True)\n    date_of_birth = models.DateField(blank=True,null=True)\n</code></pre>\n<p>add in settings.py name of your model which you created in my case <strong>CustomUser</strong> is the user model. registred in setttings.py to make it the default user model,</p>\n<pre><code>#settings.py\n\nAUTH_USER_MODEL = \'myapp.CustomUser\'\n</code></pre>\n<p>finally registred CustomUser model in <strong>admin.py</strong>\n#admin.py</p>\n<pre><code>@admin.register(CustomUser)\nclass CustomUserAdmin(admin.ModelAdmin):\n    list_display = (&quot;username&quot;,&quot;first_name&quot;,&quot;last_name&quot;,&quot;email&quot;,&quot;date_of_birth&quot;, &quot;mobile_no&quot;)\n</code></pre>\n<p>then run command <strong>python manage.py makemigrations</strong></p>\n<p>then <strong>python manage.py migrate</strong></p>\n<p>then <strong>python manage.py createsuperuser</strong></p>\n<p>now you can see your model Default User model extended with <strong>(mobile_no ,date_of_birth)</strong></p>\n<p><a href="https://i.stack.imgur.com/TqI3s.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TqI3s.png" alt="enter image description here" /></a></p>\n'}]
['https://Stackoverflow.com/questions/44109', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2841/']