Using AuthTokens with Custom User Models

I’m converting a project I’ve been working on to an API so I can use a JS front-end framework. I copied my account app and I’m working on setting up authentication and I am using the DRF Token Authentication. When I try and migrate my database I’m getting the below error.

Operations to perform:
  Apply all migrations: account, admin, api, auth, authtoken, contenttypes, sessions
Running migrations:
  Applying authtoken.0001_initial...Traceback (most recent call last):
  File "C:\\venv\lib\site-packages\django\db\backends\", line 85, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.InvalidForeignKey: there is no unique constraint matching given keys for referenced table "account_user"

If I’m understanding the error correctly then the authtoken table doesn’t have a FK to match it to my user. I didn’t create the authtoken models so I’m not sure how I would set the FK value. I’m using an existing database from my previous project so I’m not sure if that is what is causing the problem.

Does the authtoken table have a single-column primary key?

If not, does it have any column with a unique constraint?

If neither of them are true, then you’re not going to be able to create a ForeignKey to that table - you’ll need to manage those relationships manually.

I didn’t create the authtoken table or model, I think it’s auto-generated. I pulled up the migration in VENV/rest_framework/authtoken/migrations maybe this will help.

from django.conf import settings
from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [

    operations = [
                ('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
                ('created', models.DateTimeField(auto_now_add=True)),
                ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),

AUTH_USER_MODEL = 'account.User'


class User(AbstractBaseUser):
    email = models.EmailField(unique=True, max_length=200)
    # username = models.CharField(max_length=30, unique=True)
    first_name = models.CharField(max_length=240)
    last_name = models.CharField(max_length=240)
    date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    hide_email = models.BooleanField(default=True)

    objects = MyAccountManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def __str__(self):
        return "{} {}".format(self.first_name, self.last_name).title()

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return True

Look at your User table as it has been created in the database.

What is it’s primary key?

Ahh, I see in postgres both id and email are flagged at PKs. In my User model I have email set to unique=True. does that automatically set it as a PK if I don’t specify something as a PK? I just looked at my migration files and email is set to unique, not PK.

I altered the table in Postgres and it resolved my issue. I’m just curious how that happened

If you don’t specify something as PK, Django will auto-create a field named id to be the PK.

Is that PG Admin you’re looking at here? I wouldn’t place too much importance on what it’s reporting to you. There’s a chance that it doesn’t know how to report a unique key outside of referring to it as the primary key.

When I need to check something like this, I use pg_dump to dump the schema to see what PostgreSQL thinks it needs to do to recreate that schema.