Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

django.db.utils.ProgrammingError: foreign key referenced-columns list must not contain duplicates #202

Open
dom-devel opened this issue Nov 17, 2023 · 1 comment

Comments

@dom-devel
Copy link

dom-devel commented Nov 17, 2023

Hello all,

Quick summary

I'm getting

django.db.utils.ProgrammingError: foreign key referenced-columns list must not contain duplicates when I attempt to run any migrations at all on a new starter project.}

I think there must be something basic I'm missing, but I can't find it in issues or documentation.

Detailed

I'm trying to get a basic starter case going and I can't get a single migration to work, so I think I'm missing something simple

from django_multitenant.models import TenantModel
from django.db import models


class Account(TenantModel):
    name = models.CharField(max_length=255)
    contact_info = models.TextField()

    class TenantMeta:
        tenant_field_name = "id"
        
    class Meta:
        unique_together = ["id"]

    def __str__(self):
        return self.name

I create a basic Account tenant.

I then try to add it to the users with database backend enabled. I get a basic user migration

class User(TenantModelMixin, AbstractBaseUser, PermissionsMixin, IndexedTimeStampedModel):
    email = models.EmailField(max_length=255, unique=True)
    is_staff = models.BooleanField(
        default=False, help_text=_("Designates whether the user can log into this admin site.")
    )
    is_active = models.BooleanField(
        default=True,
        help_text=_(
            "Designates whether this user should be treated as "
            "active. Unselect this instead of deleting accounts."
        ),
    )
    name = models.CharField(max_length=255)
    # Custom fields
    account = models.ForeignKey(
        Account,
        on_delete=models.CASCADE,
        related_name="users",
        null=True,
        blank=True,
    )
    tenant_id = "account_id"
    objects = UserManager()

    USERNAME_FIELD = "email"

    class Meta:
        unique_together = ["id", "account"]
        

class Migration(migrations.Migration):
    initial = True

    dependencies = [
        ("auth", "0012_alter_user_first_name_max_length"),
        ("accounts", "0001_initial"),
    ]

    operations = [
        migrations.CreateModel(
            name="User",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("password", models.CharField(max_length=128, verbose_name="password")),
                (
                    "last_login",
                    models.DateTimeField(blank=True, null=True, verbose_name="last login"),
                ),
                (
                    "is_superuser",
                    models.BooleanField(
                        default=False,
                        help_text="Designates that this user has all permissions without explicitly assigning them.",
                        verbose_name="superuser status",
                    ),
                ),
                (
                    "created",
                    model_utils.fields.AutoCreatedField(
                        db_index=True,
                        default=django.utils.timezone.now,
                        editable=False,
                        verbose_name="created",
                    ),
                ),
                (
                    "modified",
                    model_utils.fields.AutoLastModifiedField(
                        db_index=True,
                        default=django.utils.timezone.now,
                        editable=False,
                        verbose_name="modified",
                    ),
                ),
                ("email", models.EmailField(max_length=255, unique=True)),
                (
                    "is_staff",
                    models.BooleanField(
                        default=False,
                        help_text="Designates whether the user can log into this admin site.",
                    ),
                ),
                (
                    "is_active",
                    models.BooleanField(
                        default=True,
                        help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
                    ),
                ),
                (
                    "account",
                    django_multitenant.fields.TenantForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="users",
                        to="accounts.account",
                    ),
                ),
                (
                    "groups",
                    models.ManyToManyField(
                        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_set",
                        related_query_name="user",
                        to="auth.group",
                        verbose_name="groups",
                    ),
                ),
                (
                    "user_permissions",
                    models.ManyToManyField(
                        blank=True,
                        help_text="Specific permissions for this user.",
                        related_name="user_set",
                        related_query_name="user",
                        to="auth.permission",
                        verbose_name="user permissions",
                    ),
                ),
            ],
            options={
                "unique_together": {("id", "account")},
            },
            bases=(django_multitenant.mixins.TenantModelMixin, models.Model),
        ),
    ]

And it fails because of the double account_id: foreign key referenced-columns list must not contain duplicates

CREATE TABLE "users_user" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "password" varchar(128) NOT NULL, "last_login" timestamp with time zone NULL, "is_superuser" boolean NOT NULL, "created" timestamp with time zone NOT NULL, "modified" timestamp with time zone NOT NULL, "email" varchar(255) NOT NULL UNIQUE, "is_staff" boolean NOT NULL, "is_active" boolean NOT NULL, "account_id" bigint NULL);
CREATE TABLE "users_user_groups" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "user_id" bigint NOT NULL, "group_id" integer NOT NULL);
CREATE TABLE "users_user_user_permissions" ("id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "user_id" bigint NOT NULL, "permission_id" integer NOT NULL);

-- The bad lines:
ALTER TABLE "users_user" ADD CONSTRAINT "users_user_id_account_id_e2e2a14b_uniq" UNIQUE ("id", "account_id");
ALTER TABLE "users_user" ADD CONSTRAINT "users_user_account_id_account_i_985fcd95_fk_accounts_" FOREIGN KEY ("account_id", "account_id") REFERENCES "accounts_account" ("id", "id") DEFERRABLE INITIALLY DEFERRED;

I can't find any other issues related to this so I think I'm just missing something very simple. Could someone point me in the right direction?

@h0m4m
Copy link

h0m4m commented Sep 9, 2024

hey, did you find a solution for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants