我有以下模型(为了清楚起见,我遗漏了def __unicode__(...)
):
class Person(models.Model):
first_name = models.CharField(max_length=64, null=True, blank=True)
middle_name = models.CharField(max_length=32, null=True, blank=True)
last_name = models.CharField(max_length=64, null=True, blank=True)
class MinorResident(Person):
move_in_date = models.DateField(null=True)
move_out_date = models.DateField(null=True)
natural_child = models.NullBooleanField()
class OtherPerson(Person):
associate_all_homes = models.BooleanField(default=False)
我有以下使用MinorResident对象创建OtherPerson对象的视图方法,如:
def MinorToAdult(request, minor):
p = Person.objects.get(id=minor.person_ptr_id)
o = OtherPerson(p.id)
o.__dict__.update(p.__dict__)
o.save()
return True
这一切都很有效,但我仍然在minoresident表中有一条记录,指向person_ptr_id的人员记录。我在otherperson表中也有一个指针记录,同一个person_ptr_id指向同一个人,并显示切换之前的所有数据,但是使用了OtherPerson对象而不是MinorResident对象。所以,我想删除MinorResident对象,而不删除父类Person对象。我想我可以做类似的事情:
p = Person.objects.get(id=minor.person_ptr_id)
o = OtherPerson()
o.__dict__.update(p.__dict__)
o.save()
minor.delete()
return True
但是如果我能帮助它,我想在Person表中没有新的记录,因为它真的不是一个新人,只是一个现在成年人。也许我可以这样做吗?或者有更好的方法来处理模型嬗变吗?
p = Person.objects.get(id=minor.person_ptr_id)
o = OtherPerson(p.id)
o.__dict__.update(p.__dict__)
o.save()
minor.person_ptr_id = None
minor.delete()
return True
我看了SO #3711191: django-deleting-object-keeping-parent,但我希望得到更好的答案。
答案 0 :(得分:6)
在Django 1.10.4+上,您可以使用keep_parents
选项:
minor.delete(keep_parents=True)
否则我建议您使用deletion.Collector
进行手动收集:
from django.db.models import deletion
collector = deletion.Collector(using=minor._state.db)
collector.add([minor])
collector.delete()
答案 1 :(得分:4)
选项1
明确指定您的parent_link
字段并使用非托管模型。
class MinorResident(Person):
person = models.OneToOneField(
Person,
parent_link = True,
primary_key = True,
db_column = 'person_id'
)
move_in_date = models.DateField(null=True)
move_out_date = models.DateField(null=True)
natural_child = models.NullBooleanField()
class UnmanagedMinorResident(models.Model):
person = models.OneToOneField(
Person,
primary_key = True,
db_column = 'person_id'
)
move_in_date = models.DateField(null=True)
move_out_date = models.DateField(null=True)
natural_child = models.NullBooleanField()
class Meta:
managed = False
db_table = MinorResident._meta.db_table
现在您可以在不删除父行的情况下调用UnmanagedMinorResident.delete()
。
选项#2
使用原始SQL查询
from django.db import connection
minor = # MinorResident object
c = connection.cursor()
table = MinorResident._meta.db_table
column = MinorResident._meta.pk.column
# In this specific case it is safe to not escape.
sql = "DELETE FROM {0} WHERE {1}={2}".format(table, column, minor.pk)
c.execute(sql)
但您应该更改数据模型并为成人和未成年人使用相同的表格。您存储在MinorResident
模型中的属性不属于那里,它们属于MinorResident
与其移入/移出的实体之间的关系。