2

For my application, the email field in the Django User model should be required, but by default it's optional.

I searched this question but most answers I found were talking about making the email field required in the customised UserCreationForm for example:

class CustomUserForm(UserCreationForm):
    """Provide a view for creating users with only the requisite fields."""

    class Meta:
        model = User
        # Note that password is taken care of for us by auth's UserCreationForm.
        fields = ('username', 'email')

    def __init__(self, *args, **kwargs):
        super(CustomUserForm, self).__init__(*args, **kwargs)
        self.fields['email'].required = True

but I want to make the email mandatory in the User model as well because I was thinking maybe ModelForm are a frontend thing and the required condition maybe be turned off by the user by using the chrome dev tools, am I wrong? Will making the email required in ModelForm is same as making it required in the user model as well, or can I override the user model to make the email required?

yogeshiitm
  • 179
  • 1
  • 17
  • 2
    A Form is *not* only frontend, if you use a form to process the data (typically constructing `CustomUserForm(request.POST)`, it will also validate, at the server side if the user has entered an `email` address). – Willem Van Onsem Jan 12 '21 at 20:59

3 Answers3

2

Maybe ModelForm are a frontend thing and the required condition maybe be turned off by the user by using the chrome dev tools, am I wrong?

You are correct that a user can use tools to make an input item not required, in fact you can often alter the DOM and thus alter the HTML form, or even more simply make use of a tool like curl to make a POST request where you can post arbitrary data.

But a Form (and by extent an ModelForm) does not only render the form in HTML, it is also used to validate the data. This thus means that if you use a view with:

def my_view(request):
    if request.method == 'POST':
        form = CustomUserForm(request.POST, request.FILES)
        if form.is_valid():
            # …
        # …
    # …

then the form.is_valid() will return False if the user did not fill in an email address. A form is thus used to validate, clean data, store data in a model, and render a HTML form.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1
from django.contrib.auth.models import User
from django.db import models

User.add_to_class('email', models.EmailField(blank=False))



1

in your settings file

AUTH_USER_MODEL = 'yourapp.User'

in your models

from django.db import models
from django.contrib.auth.models import AbstractUser, Permission, Group
from django.utils.translation import gettext_lazy as _


class User(AbstractUser):
    groups = models.ManyToManyField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_(
            'The groups this user belongs to. A user will get all permissions '
            'granted to each of their groups.'
        ),
        related_name="user_groups",
        related_query_name="user",
    )
    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('user permissions'),
        blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_permissions",
        related_query_name="user",
    )

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['email']

    # here you can add new fields and attributes

    class Meta:
        permissions = (
            # here you can add pressiion
        )

in your admin

from custodia.models import User
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _


@admin.register(User)
class UserAdmin(UserAdmin):
    list_display = ('email', 'first_name', 'last_name', 'customer', 'is_staff', 'is_active')
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Aditional info'), {'fields': ('your_new_fields',)}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )

    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups', 'customer')

  • 1
    I am quite new to Django so I don't understand, like if we are inheriting from `AbstractUser` then why do we need to add so many things like `groups`, `user_permissions` etc. won't the AbstractUser take care of all this? Also, I don't understand the code in `admin.py`, what is it for? – yogeshiitm Jan 13 '21 at 00:01
  • the admin file is only need it if you are using the admin site – Cesar Abel Ramirez Jan 13 '21 at 07:42