【问题标题】:How to check if foreign key exists?如何检查外键是否存在?
【发布时间】:2020-01-18 05:06:50
【问题描述】:

在这里,我有一个名为 Staff 的模型,它与 django User 模型具有 OneToOne 关系,并且与 Organization 模型具有 ForeignKey 关系。在删除组织时,我想检查组织是否存在于 Staff 模型中.如果它存在于人员模型中,那么我不想删除,但如果它不存在于其他表中,那么我只想删除。

我该怎么做?

我收到以下代码的错误:

Exception Type: TypeError
Exception Value:    
argument of type 'bool' is not iterable

models.py

class Organization(models.Model):
    name = models.CharField(max_length=255, unique=True)
    slug = AutoSlugField(unique_with='id', populate_from='name')
    logo = models.FileField(upload_to='logo', blank=True, null=True)

class Staff(models.Model):
    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name='staff')
    name = models.CharField(max_length=255, blank=True, null=True)
    organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, blank=True, null=True,
                                     related_name='staff')

views.py

def delete_organization(request, pk):
    organization = get_object_or_404(Organization, pk=pk)
    if organization in organization.staff.all().exists():
        messages.error(request,"Sorry can't be deleted.")
        return redirect('organization:view_organizations')
# also tried
# if organization in get_user_model().objects.filter(staff__organization=organizatin).exists():
    elif request.method == 'POST' and 'delete_single' in request.POST:
        organization.delete()
        messages.success(request, '{} deleted.'.format(organization.name))
        return redirect('organization:view_organizations')

【问题讨论】:

  • 请您显示完整的错误跟踪。

标签: django django-views foreign-keys


【解决方案1】:

检查应该是:

def delete_organization(request, pk):
    organization = get_object_or_404(Organization, pk=pk)
    if organization.staff.exists():
        messages.error(request, "Sorry can't be deleted.")
        return redirect('organization:view_organizations')
    # ...

但是,您可以通过在 get_object_or_404 中进行适当的过滤来优化上述内容:

def delete_organization(request, pk):
    organization = get_object_or_404(Organization, pk=pk, is_staff__isnull=True)
    # ...

如果组织不存在,或者组织存在但仍有一些员工,这将引发 404。

根据您编写的逻辑,您希望防止在仍有人员的情况下删除组织。您也可以在 model 层中设置这样的逻辑,使用 models.PROTECT 作为 on_delete 处理程序:

class Staff(models.Model):
    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name='staff')
    name = models.CharField(max_length=255, blank=True, null=True)
    organization = models.ForeignKey(Organization, on_delete=models.PROTECT, blank=True, related_name='staff')

现在 Django 将帮助您强制您不要意外删除仍有相关人员的Organization,这样会更安全。

【讨论】:

    【解决方案2】:

    除了@Willem 先生的回答之外,您还可以将模型 Fk 更改为 on_delete=models.PROTECT,然后创建这样的视图:

    from django.db.models.deletion import ProtectedError
    def delete_organization(request,id):
        obj = get_object_or_404(Organization,id=id)
        try:
            obj.delete()
            return return_to_somewhere
    except ProtectedError:
        return 'show some error message'   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2021-02-08
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多