Code

Opened 6 years ago

Closed 3 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.

Attachments (0)

Change History (7)

comment:1 Changed 6 years ago by anonymous

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I agree

comment:2 Changed 6 years ago by anonymous

  • Needs documentation set
  • Needs tests set
  • Patch needs improvement set

comment:3 Changed 6 years ago by serialx

  • Triage Stage changed from Unreviewed to Design decision needed

comment:4 Changed 4 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 3 years ago by julien

  • Component changed from Core framework to Database layer (models, ORM)

comment:6 Changed 3 years ago by baumer1122

  • Severity set to Normal
  • Type set to New feature

comment:7 Changed 3 years ago by jacob

  • Easy pickings unset
  • Resolution set to wontfix
  • Status changed from new to closed
  • 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.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.