Search code examples
pythondjangodjango-modelsdjango-signals

Django registration different type users with different fields


I need to create two different users: Gym and Client. The client should theoretically be connected by a many-to-many bond because he can be enrolled in multiple gyms. My doubt is about user registration. I found this around:

class User(AbstractUser):
    is_gym = models.BooleanField(default=False)
    is_client = models.BooleanField(default=False)

class Gym(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    user.is_gym = True

class Client(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    gyms = models.ManyToManyField(Gym, related_name='clients')
    user.is_client = True

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        if instance.is_gym:
            Gym.objects.create(user=instance)
        elif instance.is_client:
            Client.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    if instance.is_gym:
        instance.gym.save()
    elif instance.is_client:
        instance.client.save()

My doubts are two:

  • If I wanted to register users with a button "I am a gym" or "I am a customer" with this code, theoretically I could not do it because User class differs, the gym does not have a surname for example.
  • With this code I should create the Gym and Client class populated at a later time so I should make a second form after verifying the account.

Solution

  • I would push a lot of that information onto the Gym and Client models, as you say, a gym doesn't have a surname. You could use the base User model for authentication and set the username to an email address. The Client model can then have fields for first name, surname, and anything else. The Gym model would just have a name field.

    In terms of managing this, you can create a form for both profiles and render one depending on whether the User clicks gym or client in the next view.