Django's user model treats usernames case-sensitively by default. This is basically never what you want.

It is quite common these days to treat the e-mail address as the login name. E-mail addresses are case-sensitive according to the relevant standards, but in practice they are not. Users will arbitrarily switch between different ways of writing the same e-mail address. Depending on how you deal with user account creation, they will not only have trouble logging in, but might even accidentally create multiple accounts.

Fortunately, there is a rather simple and elegant solution to this problem. Michal Petrucha pointed me at it in the Django IRC channel (thanks!).

https://groups.google.com/d/msg/django-developers/SW7_qI81G58/2gzMQZyfBAAJ

Django supports CITextField / CIEMailField natively since version 2.1.

As Carl says, the main trouble is setting up the necessary Postgres extension. A normal Django migration will work nicely if you apply your migrations as database superuser, but you probably do not do that, for good reasons.

You can add the extension to the template1 database instead. That way, it will be available in all newly created databases (including the test database Django automatically creates for you when running tests).

For the typical virtualenv development setup, just adding a line to the project's README file is fine, in my opinion.

Our project at work also supports docker-compose. To install the extension there, we ended up doing this:

version: '2.1'

services:
  postgres:

    image: postgres
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgres
      - ./sql:/docker-entrypoint-initdb.d/

Add a file at sql/install_citext.sql (relative to docker-compose.yml) with the following content:

/* Current DB */
CREATE EXTENSION IF NOT EXISTS citext;

/* New DBs */
\c template1
CREATE EXTENSION IF NOT EXISTS citext;

Rebuild your database Docker image.

That's it. You can now just change the necessary field in your model to CITextField or CIEmailField, and run makemigrations. This ensures uniqueness during user creation and allows case-insensitive logins. No need to customize your forms / serializers / model managers :)

Sources: