我有下一个型号:
class Target(models.Model):
name = models.CharField(max_length=100, blank=False)
class SubTarget(models.Model):
target = models.ForeignKey(Target, related_name='sub_targets')
name = models.CharField(max_length=100, blank=True, null=True, default='')
例如,我运行下一个代码:
target = Target(name='test-target')
target.save()
sub_target = SubTarget(name='test-sub-target, target=target)
sub_target.save()
所以现在我有了带外键的sub_target对象。
我的目标序列化程序如下:
class TargetSerializer(serializers.ModelSerializer):
class Meta:
model = Target
fields = ('id', 'name', 'sub_targets')
depth = 1
read_only_fields = ('sub_targets',)
和适当的观点:
class TargetDetail(generics.RetrieveUpdateDestroyAPIView):
model = Target
serializer_class = TargetSerializer
所以,没有什么能阻止我删除目标创建的带外键的对象。而且,此操作删除还与 sub_target 对象相关。我该如何避免这种行为?
答案 0 :(得分:7)
我不确定,但我想您在询问如何在删除Target对象时阻止删除SubTarget对象。默认情况下,Django模拟ON DELETE CASCADE。您可以使用on_delete关键字控制此行为。
所以:
class Target(models.Model):
name = models.CharField(max_length=100, blank=False)
class SubTarget(models.Model):
target = models.ForeignKey(Target, related_name='sub_targets',
null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=100, blank=True, null=True, default='')
答案 1 :(得分:2)
在寻找一种方法来检查是否可以在django中删除模型实例之后,我遇到了很多样本,但是没有按预期工作。希望这个解决方案可以提供帮助。
首先创建一个可以由其他模型继承的抽象模型类
class ModelIsDeletable(models.Model):
name = models.CharField(max_length=200, blank=True, null=True, unique=True)
description = models.CharField(max_length=200, blank=True, null=True)
date_modified = models.DateTimeField(auto_now_add=True)
def is_deletable(self):
# get all the related object
for rel in self._meta.get_fields():
try:
# check if there is a relationship with at least one related object
related = rel.related_model.objects.filter(**{rel.field.name: self})
if related.exists():
# if there is return a Tuple of flag = False the related_model object
return False, related
except AttributeError: # an attribute error for field occurs when checking for AutoField
pass # just pass as we dont need to check for AutoField
return True, None
class Meta:
abstract = True
因此,假设我们有三个模型组织和部门以及StaffType 这么多部门都可以在一个组织中 组织有一个特定的StaffType
class StaffType(ModelIsDeletable):
pensionable = models.BooleanField(default=False)
class Organization(ModelIsDeletable):
staff_type = models.ForeignKey(to=StaffType)
class Department(ModelIsDeletable):
organization = models.ForeignKey(to=Organization, to_field="id")
所以,在添加一些您要删除组织模型实例的信息后,请说 已经与部门联系在一起
例如我们有 组织表=> (name = Engineering,pk = 1) 部门表=> (name = Developer,organization_fk = 1,pk = 1)
现在,当您尝试使用pk
获取组织后删除组织a_org = Organization.objects.get(pk=1)
有了这个,您可以检查它是否可删除
deletable, related_obj = a_org.is_deletable()
if not deletable:
# do some stuff with the related_obj list
else:
# call the delete function
a_org.delete()
答案 2 :(得分:1)
也许你可以尝试另一种方式,我只是用我的项目,使用Django 1.8
instance = get_object_or_404(MyModel, pk=pk)
eliminate = True
for robject in instance._meta.get_all_related_objects():
if robject is not None:
if robject.related_model.objects.filter(**{robject.field.name: instance}).exists() and eliminate:
eliminate = False
if eliminate:
instance.delete()
# additional code
else:
# additional code
pass
答案 3 :(得分:1)
延迟回复,但使用ForeignKey
上的model.PROTECT
也可以避免这种情况
target = models.ForeignKey(
Target, related_name='sub_targets', on_delete=models.PROTECT
)
class BaseModel(models.Model):
def can_delete(self):
# get all the related object to be deleted
for related in get_candidate_relations_to_delete(self._meta):
field = related.field
if field.remote_field.on_delete == models.PROTECT:
# check for relationship with at least one related object
related = related.related_model.objects.filter(**{related.field.name: self})
if related.exists():
return False, related
return True, None
class Meta:
abstract = True
答案 4 :(得分:0)
您可以覆盖模型的删除操作,如:
class Target(models.Model):
name = models.CharField(max_length=100, blank=False)
def delete(self, *args, **kwargs):
for robject in self._meta.get_all_related_objects():
if robject is not None:
q = Q(**{"%s__id" % robject.field.name: self.id})
if robject.model.objects.filter(q).exists():
raise Exception("Item has active reference.")
try:
with transaction.atomic():
super(Target, self).delete(*args, **kwargs)
except Exception, exp:
raise exp
请注意,如果相关对象与另一个对象没有反向关系,则它不起作用。