Reputation: 66
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.
Upvotes: 1
Views: 801
Reputation: 12068
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.
Upvotes: 1
Reputation: 27311
You can use to_field
to create fkeys to non-pk fields of another model, however, those fields need to have a unique constraint (i.e. 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.
Upvotes: 1