1

I'm relatively new(er) to django but very excited to learn such a versatile framework. I'm working on a project where I will have 2 user types, account 1 and account 2. Account 2 will have the ability to "add a user" to their account. Think of account 2 as a company who can add users to their company.

So far I've extended the generic User model and have created a class for each of the account types but I'm not sure if I'm doing it correctly. Ultimately I will want to create a login/register form for each of the account types - similar to how ziprecruiter functions so some advice on how to approach that would be awesome too if possible.

class User(AbstractBaseUser, PermissionsMixin):
    email           = models.EmailField(_('email address'), unique=True)
    is_staff        = models.BooleanField(default=False)
    is_active       = models.BooleanField(default=True)
    date_joined     = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self):
        return self.email

class account1(User):
    profile         = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+', null=True)
    # account 2 fields here
    first_name      = models.TextField(max_length=30, blank=True)
    last_name       = models.TextField(max_length=30, blank=True)
    location        = models.TextField(max_length=30, blank=True)

    class Meta:
        db_table = 'account1_user'

class account2(User):
    profile = models.ForeignKey(User, on_delete=models.CASCADE, related_name='+')
    # account2 user fields here

    class Meta:
        db_table = 'account2_user'

Am I doing this correctly? What's the best approach to creating a login/registration form for each type of account? What's the best approach to creating a model that will allow for a user of a user type (if that makes sense)?

1
  • What is the question tho? Commented Jan 5, 2020 at 13:51

2 Answers 2

2

Rule of thumb is no matter what your business logic, always use one User model for your application. if you want multiple types of user then you could use attributes to determine user types. For example, in my application i want three types of user, Admin,Broker and Client. Here is how we can do this.

class UserManager(BaseUserManager):

    def create_client(self, username, first_name, last_name, email, phone, password=None):
        user = self.model(
            username=username,
            first_name=first_name,
            last_name=last_name,
            phone=phone,
            email=self.normalize_email(email)
        )
        user.set_password(password)
        user.is_client = True
        user.save(using=self.db)
        return user

    def create_reseller(self, username, first_name, last_name, email, phone, password=None):
        user = self.create_client(username, first_name, last_name, email, phone, password)
        user.is_reseller = True
        user.save()
        return user

    def create_admin(self, username, first_name, last_name, email, phone, password=None):
        user = self.create_reseller(username, first_name, last_name, email, phone, password)
        user.is_admin = True
        user.save()
        return user


    class User(AbstractBaseUser, PermissionsMixin):
        is_superuser = None

        REQUIRED_FIELDS = ["username", "first_name", "last_name", "phone"]
        EMAIL_FIELD = "email"
        USERNAME_FIELD = 'email'

        objects = UserManager()

        email = models.EmailField(unique=True)
        username = models.CharField(max_length=DefaultModel.MAX_LENGTH)
        first_name = models.CharField(max_length=DefaultModel.MAX_LENGTH)
        last_name = models.CharField(max_length=DefaultModel.MAX_LENGTH)
        phone = PhoneNumberField(unique=True)

        is_admin = models.BooleanField(default=False)
        is_reseller = models.BooleanField(default=False)
        is_client = models.BooleanField(default=False)
        # storing timestamps for users.
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
        added_by = models.ForeignKey("self", models.CASCADE, default=None, null=True)

So what i did, i'm using custom UserManager Class which is responsible for generating User Model objects and i've implemented methods for generating for all types of users Client, Broker and Admin.

DefaultModel is actually class which i'm using as constants for setting default values for models. Here is what it looks like:

class DefaultModel:
    MAX_LENGTH = 1000
    MYSQL_UNIQUE_LENGTH = 255

If you don't know about objects in models you may learn about it from Django docs. Custom User Models
Django Managers

Sign up to request clarification or add additional context in comments.

6 Comments

Okay that makes sense. My question now is that User model should just contain fields that are relative to both user types? What about for when fields that pertain to broker but not client and vice versa - how would you approach that? I assume maybe creating a profile class for each of them?
You can override the User.clean method to add some conditional validation that raises ValidationErrors when conditionally required fields are missing
@Nick Creating individual class for each type of user is also better idea. It's better to add validation in that model (as Lain suggested for user model) to check if user type is Client or admin depending on for what user you are creating. And yes user model can contains fields which are relative to both users. It's depends on you what you like to have and which way is much easier to maintain application in future.
Would going the route of using Choices to determine which type of user it is be beneficial at all?
This is good. Is there any way to avoid saving twice?
|
0

The question was asked long time ago but I would like to share my thoughts.By the look of your code, it is not quite clear of what you are trying to achieve. If you would like to create user based on type then @Ammad Khalid's solution is good.

However, if you wanted to extends user because some columns are specific child related then you can implement like this,

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.CharField(max_length=100)

The above extends the user model and creates a new table in your database.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.