Django 2.2.1:修改OneToOneField的关系

时间:2019-06-04 05:44:20

标签: django django-models

在Django 2.2.1中,我有两个通过OneToOneField相关的模型:

class Woman(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Man(models.Model):
    name = models.CharField(max_length=100)
    wife = models.OneToOneField(
        Woman,
        related_name = 'husband',
        null=True,
        blank=True,
        on_delete=models.SET_NULL
    )

    def __str__(self):
        return self.name

(为简化起见,是非对等的。)但是众所周知,婚姻失败了。但是,我在修改关系方面花费了很多时间:

>>> john = Man.objects.create(name='John')
>>> alice = Woman.objects.create(name='Alice')
>>> susan = Woman.objects.create(name='Susan')
>>> john.wife = alice
>>> alice.husband
<Man: John>
# After the divorce...
>>> john.wife = susan
>>> susan.husband
<Man: John>
>>> alice.husband
<Man: John>
>>> susan.save()

Traceback (most recent call last):
...
django.db.utils.IntegrityError: UNIQUE constraint failed: appname_woman.husband_id

好吧,这很有道理:两个Woman对象不能拥有相同的丈夫(至少根据美国现行法律而言)。没问题;如果我从恋爱关系中删除了原来的妻子怎么办?

>>> alice.husband = None
>>> alice.save()
>>> alice.husband # None
>>> susan.husband
<Man: John>
# Oh good, no errors. And John is now married to Susan... right? Wrong.
>>> john.save()

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/project/venv/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 415, in __get__
    self.related.get_accessor_name()
appname.models.Man.wife.RelatedObjectDoesNotExist: Man has no wife.

完成这项工作的唯一方法似乎是确保在约翰再婚之前离婚:

# Starting with a clean database
>>> john = Man.objects.create(name='John')
>>> alice = Woman.objects.create(name='Alice')
>>> susan = Woman.objects.create(name='Susan')
>>> john.wife = alice
>>> alice.husband
<Man: John>
# The marriage was brief...
>>> john.wife = None
>>> john.save()
>>> john.wife = susan
>>> john.save()
>>> susan.save()
>>> alice.save()
# Everybody's happy, we hope.

真是一团糟!现在,这是我的问题:我该如何编写代码以确保将Man对象分配给新的Man.wife时,先前的Man.wife被删除并通过验证?

2 个答案:

答案 0 :(得分:0)

尝试此功能

from django.core.exceptions import ObjectDoesNotExist


def marriage(man_name, women_instance):
    try:
        women_instance.husband = None
        women_instance.save()
        return Man.objects.create(name=man_name, wife=women_instance)
    except ObjectDoesNotExist:
        return Man.objects.create(name=man_name, wife=women_instance)

用法

women_instance = Woman.objects.get(name="bar")
man_name = "Foo"
man_instance = marriage(man_name, women_instance)

答案 1 :(得分:0)

我认为您正在为此付出更多的努力。修改后,您只是没有保存john

这将起作用:

>>> john = Man.objects.create(name='John')
>>> alice = Woman.objects.create(name='Alice')
>>> susan = Woman.objects.create(name='Susan')
>>> john.wife = alice
>>> john.save()
>>> john.wife = susan
>>> john.save()