Opened 8 years ago

Closed 5 years ago

#7689 closed New feature (wontfix)

add 'symmetrical' argument to OneToOneField('self')

Reported by: aldo.deluca@… Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

I would like to see a new feature on one-to-one relationship.
It would be good if OneToOneField had a 'symmetrical' argument to make this relationship bidirectional.
This could be available only for self one-to-one relationships.
An example model :

class Person(models.Model):
        name=models.CharField(max_length=100)
        spouse=models.OneToOneField('self',symmetrical=True)
        best_friend=models.OneToOneField('self',symmetrical=False)

John is necessarily his spouse's spouse but he may not be his best friend's best friend.
The same feature has already been added to many-to-many relationships.
Thanks to Django developers.

Change History (7)

comment:1 Changed 8 years ago by anonymous

I agree

comment:2 Changed 8 years ago by anonymous

Needs documentation: set
Needs tests: set
Patch needs improvement: set

comment:3 Changed 8 years ago by Sung-jin Hong

Triage Stage: UnreviewedDesign decision needed

comment:4 Changed 7 years ago by jonozzz

This is my workaround for the symmetrical OneToOneField.

First I started to play around with OneToOneField and then add connect() and disconnect() methods to pair the two, but it gets so un-pythonic and too messy when it comes to deletions.
It seems that the easiest way is to use a ManyToMany field behind the scenes so that when you kill one spouse the other remains alive :)

Thoughts?

class Person(models.Model):
    name=models.CharField(max_length=100)
    _spouse=models.ManyToManyField('self')
    best_friend=models.OneToOneField('self',symmetrical=False)

    def get_spouse(self):
        try:
            return self._spouse.all()[0]
        except IndexError:
            return None

    def set_spouse(self, value):
        self._spouse.clear()
        if value:
            return self._spouse.add(value)

    spouse = property(get_spouse, set_spouse)

comment:5 Changed 6 years ago by Julien Phalip

Component: Core frameworkDatabase layer (models, ORM)

comment:6 Changed 6 years ago by Peter Baumgartner

Severity: Normal
Type: New feature

comment:7 Changed 5 years ago by Jacob

Easy pickings: unset
Resolution: wontfix
Status: newclosed
UI/UX: unset

It took Alex and I about 5 minutes to understand the use case here, and that's probably a bad sign for usability. So I'm going to mark this as wontfix: adding a confusing, possibly complicated feature doesn't seem like a good idea. Further, it's fairly easy to implement in a custom save function; something like:

def save(self, *args, **kwargs):
    super(Person, self).save()
    self.spouse.spouse = self

Ought to do the trick.

Thanks for the idea; sorry it's not a great fit for Django.

Note: See TracTickets for help on using tickets.
Back to Top