Automatically create a one-to-one relationship when using the inverse field

When you create two instances of the model and connect them using OneToOneField, the connection is created and saved automatically when the object is created:

from django.db import models

class MyModel(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    next = models.OneToOneField('self', on_delete=models.SET_NULL, related_name='prev', null=True, blank=True)

>>> m2 = MyModel.objects.create(name="2")
>>> m1 = MyModel.objects.create(name="1", next=m2)
>>> m2.prev
<MyModel: 1>
>>> m2.refresh_from_db()
>>> m2.prev
<MyModel: 2>

However, when creating the same connection, but using the opposite field, the creation is also performed automatically, but is not saved.

>>> m1 = MyModel.objects.create(name="1")
>>> m2 = MyModel.objects.create(name="2", prev=m1)
>>> m1.next
<MyModel: 2>
>>> m1.refresh_from_db()
>>> m1.next

Note that the last statement does not print anything, as it returns None


How can I always keep this relation when creating using the inverse field without having to manually use it .save()every time?

+6
2

, pre_save/post_save, . , , , !

from django.db.models.signals import post_save
from django.dispatch import receiver

class MyModel(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    next = models.OneToOneField('self', on_delete=models.SET_NULL, related_name='prev', null=True, blank=True)

@receiver(post_save, sender=MyModel)
def mymodel_post_save(sender, instance, **kwargs):
     if hasattr(instance, 'prev'): # if prev exists
          # now check if prev is added next
          if not instance.prev.next: # if next is not present 
                 instance.prev.next = instance
                 MyModel.objects.filter(
                     pk=instance.prev.pk
                 ).update(next=instance)
+5

.

, .

, MyModel.objects.create , . , , .

:

m2 = MyModel.objects.create(name="2", prev=m1)

, , .create m1, m1 - , ( next)

? . PEP 20

, .

- - .

- :

class MyModel(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    prev = models.OneToOneField('self',
                                null=True,
                                blank=True,
                                related_name='next',
                                on_delete=models.SET_NULL)

, , prev .

+3

Source: https://habr.com/ru/post/1016174/


All Articles