Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have a OneToOne relationship between two objects of the same class in a Django app. Is it possible to enforce the uniqueness of this relationship?

I have the following in my app:

class University(models.Model):
    ...
    sister_university = models.OneToOneField('self', related_name = 
                        'university_sister_university', 
                        blank=True, null=True, 
                        on_delete=models.SET_NULL)

I only want a university to be related to one other university in both directions of that relationship.

For example, in the database, if I select university A as the sister_university of university B, I only want to be allowed to select university B as the sister_university under university A also. However, as it is, that second relationship is not enforced.

For example: Right now, under the Django Admin site, if I first select university A as the sister university of university B, I am still able to select any other university as the sister university of the university A object. I’m not constrained to only selecting university B.

Is it possible to enforce that uniqueness at the database level? Is there a better way of accomplishing what I’m trying to do?

like image 225
Joe Avatar asked May 15 '18 17:05

Joe


People also ask

How does Django handle one to many relationships?

To handle One-To-Many relationships in Django you need to use ForeignKey . The current structure in your example allows each Dude to have one number, and each number to belong to multiple Dudes (same with Business).

What is Onetoone field in Django?

This field can be useful as a primary key of an object if that object extends another object in some way. For example – a model Car has one-to-one relationship with a model Vehicle, i.e. a car is a vehicle. One-to-one relations are defined using OneToOneField field of django.


2 Answers

I think that what you need is to make this relationship symmetric.

You can accomplish this by overriding the save() method of the University model:

def save(self, *args, **kwargs):
    super(University, self).save()
    if self.sister_university:
        self.sister_university.sister_university = self
like image 154
Peter Sobhi Avatar answered Oct 18 '22 03:10

Peter Sobhi


I never did this kind of things, but I think that you can make this process through this way :

Method : unique_together()

You can use Options.unique_together and set your university_A and university_B as a unique pair.

unique_together = ("university_A", "university_B")

In your models.py file, you should have something like this (with maybe some issues, but the idea is there) :

class University(models.Model):
    ...
    university = models.ForeignKey('self', on_delete=models.CASCADE)
    sister_university = models.ForeignKey('self', on_delete=models.CASCADE)
    class Meta:
        unique_together     = (('university','sister_university'),)

You should find precious details there : https://docs.djangoproject.com/en/2.0/ref/models/options/

I never tried this command, but it seems to solve your issue according to your context.

like image 38
Essex Avatar answered Oct 18 '22 03:10

Essex