0

So I know I can use signals to automatically create a one-to-one related instance. (For example: Create OneToOne instance on model creation).

My situation is that the related model contains a non-null, non-blank field.

class Company(models.Model):
    name = models.CharField()

class UserProfile(models.Model):
    user = models.OneToOneField( settings.AUTH_USER_MODEL )
    company = models.ForeignKey( Company )

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile( sender, instance, created, **kwargs ):
    if created:
        UserProfile.objects.create(user=instance)

When a user is created, create_user_profile is triggered. But this causes an error Column company_id cannot be null. How do I pass company_id into the receiver? Would I need to create a custom manager in the User model? If so, would that just remove the need for signals since I can create UserProfile in the manager?

djvg
  • 11,722
  • 5
  • 72
  • 103
user3628119
  • 355
  • 5
  • 15
  • Yes, if you need to always set a Company on creation then don't use a signal. In any case you should consider using an extended User model rather than a separate UserProfile. – Daniel Roseman Jul 30 '18 at 14:42
  • Why is it better to extend User model? – user3628119 Jul 30 '18 at 14:45
  • Because then you don't have to manage two separate models at all, and none of this even comes into play. You can just add the company with same method you use to create the rest of the data. – Daniel Roseman Jul 30 '18 at 14:46

1 Answers1

0

I would recommend using your own User model, then you can add a bunch of cool class methods to it, like create and delete, which can be useful for data-integrity going forward, like preventing deletions in the delete(), enforcing the OneToOne in the create(), etc. I'm assuming you know the company when you create the user in this scenario:

class User(models.model):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True)
    @classmethod
    def create(cls, email, company):
        new_user = cls(email=email)
        new_user.save()
        new_profile = UserProfile(user=new_user, company=company)
        new_profile.save()
        return new_user
    

class Company(models.Model):
    name = models.CharField()

class UserProfile(models.Model):
    user = models.OneToOneField( User )
    company = models.ForeignKey( Company )

Then you can just create the user with:

my_user = User.create(email=new_email, company=my_company)
djvg
  • 11,722
  • 5
  • 72
  • 103
Dougyfresh
  • 586
  • 3
  • 15