简体   繁体   中英

create django user based on existing model object

I'm working on Property Management django app where my base model is Tenant with all basic info like name, surname, email etc. Willing tenants will be able to create user account so they can log in and book Gym/Cinema, but not all Tenants will need to have user account. My problem is:

How can I create new user accounts based on existing Tenant objects? Obviously user will have Tenant ForeignKey but how can I extract Tenant.name, Tenant.surname etc to more than 1 field in my user model?

ForeignKey only gives me reference to object but can I somehow access certain fields of that object during creation of new user so I make sure that Tenant.email is the same as user.email?

Edit

tenancy = (('Tenant', 'Tenant'),('Owner', 'Owner'), ('Other', 'Other'))

class Tenant(models.Model):

    name          = models.CharField(max_length=15, null=True, blank=False)
    surname       = models.CharField(max_length=30, null=True, blank=False)
    email         = models.EmailField(max_length=50, unique=True)
    phone_number  = models.CharField(max_length=20, null=True, blank=True, unique=True)
    flat          = models.ForeignKey(Flat, on_delete=models.PROTECT)
    status        = models.CharField(max_length=10, choices=tenancy, null=True, blank=False)
    stay_length   = models.CharField(max_length=20, null=True, blank=False)
    pet_licence   = models.CharField(max_length=20, null=True, blank=False)
    additional_notes= models.TextField(max_length=300, blank=True)
    date_added    = models.DateField(auto_now_add=True, null=True)
    moved_out     = models.BooleanField(default=False)
    date_moved_out= models.DateField(auto_now_add=False, null=True)

    class Meta:
        unique_together = ('name', 'surname',)


    def __str__(self):
        return f'{self.name} {self.surname}' 

Now I'd like to create user account model where name, surname, email, phone_number and flat will be ForeignKeys of Tenant model. Is it even possible to have 4 ForeignKeys from 1 object populating new model?

I've tried playing around with ForeignKey.limit_choices_to, ForeignKey.related_name, ForeignKey.to_field (this was close but field related to has to be unique which doesn't work for my case) but everything gives errors. I just want to find out if it's even possible that more than 1 ForeignKey of 1 object can be directed to multiple different fields of new model object.

You can use to_field to create fkeys to non-pk fields of another model, however, those fields need to have a unique constraint (ie unique=True ) - which seems unlikely for name/surname.

It sounds like you want a transparent access from the User model to the Tenant models fields, and that is not possible.

You can create a fkey from User to Tenant:

class User(models.Model):
    tenant = models.OneToOneField(Tenant, null=True, blank=True, related_name='user')
    ...

and then access the fields with

user = User.objects.get(...)
user.tenant.surname

to keep the fields in sync you can override the save() method:

class Tenant(...)
    ...
    def save(self, *args, **kwargs):
        if self.user:
             self.user.last_name = self.surname
             ...
             self.user.save()
        super().save(*args, **kwargs)

aside: null=True indicates that the database should allow null in the field, blank=True says that the field can be empty in the admin interface. You should probably have null=True, blank=True in most cases.

I would approach it in a way that the foreign key is in Tenant , instead of User , and define it as a nullable one-to-one . This way you keep your User model free of foreign keys:

class Tenant(models.Model):
    user = models.OneToOneField(
        User,
        related_name='tenant',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        default=None,
    )

Then to create the related user, you can add a method in your Tenant model like so:

class Tenant(models.Model):
    ...
    def create_user(self):
        if not self.user:
            user = User.objects.create(
                first_name=self.name,
                last_name=self.surname,
                ...
            )
            self.user = user
            self.save()

Have a look at the example from the docs here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM