Creating ForeignKey reference with 2 different models as choice

Viewed 41

Here is what i want to try, I have a User model inherited from Abstract user with custom manager, i need a feeld in CustomUser model to choose either Seller model or Customer model

class CustomUser(AbstractUser):
    is_seller = models.BooleanField(default=False)
    is_customer = models.BooleanField(default=False)

    user_type = ? "I want to have a choice feild to choose either Seller or 
    Customer model"

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = CustomUserManager()


class CustomUserManager(BaseUserManager):
    use_in_migrations = True


    def create_user(self, email, password=None, **extra_fields):
        if not email:
            return ValueError('Email required')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user


    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff true')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser true')

        return self.create_user(email, password, **extra_fields)


class SellerDetails(models.Model):
    pass

class CustomerDetails(models.Model):
    pass
2 Answers

Have you looked at Django Content Types Framework? Have a look at it here

This can help you in achieving what you want.

Here is a very simple to understand article on this.

GenericForeignKey is the solution. Django has a nice feature called a generic foreign key. In this particular type of field, you can save any type of object, only you have to mention which type of object is it referring to. Here I have put an example for you below:

class ModelA(models.Model):
    achar = models.CharField(
        max_length=255,
        blank=True,
        default="",
    )


class ModelB(models.Model):
    achar = models.CharField(
        max_length=255,
        blank=True,
        default="",
    )


class ModelC(models.Model):
    achar = models.CharField(
        max_length=255,
        blank=True,
        default="",
    )
    content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

Now, when creating an object for ModelC, you can either select ModelA or ModelB, then the id of the object.

If you have your own template of the CRUD page or you are using an API to make the crud operation, then it will be very easy to populate the data. If you are using a Form then you might need to make a custom field, so that you can select a context type and based on the type you see can see a dropdown list.

Related