Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if foreign key exists?

Here I have a model called Staff which has OneToOne relation with django User model and ForeignKey relation to the Organization model.Here while deleting the organization I want to check if the organization exists in Staff model or not .If it exists in Staff model then i don't want to delete but if it doesn't exists in other table then only I want to delete.

How can I do it ?

I got this error with below code:

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')
like image 869
Hello Avatar asked Mar 03 '23 10:03

Hello


1 Answers

The check should be:

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')
    # ...

You can however optimize the above, by doing proper filtering in the get_object_or_404 already:

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

This will then raise a 404 in case the organization does not exist, or the organization exists, but has still some staff.

Based on the logic you wrote, you want to prevent that you can delete an organization if there is still staff. You can set such logic in the model layer as well, by using models.PROTECT as on_delete handler:

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')

Now Django will help you enforce that you do not, by accident, remove an Organization where there is still related staff, this makes it more safe.

like image 112
Willem Van Onsem Avatar answered Apr 06 '23 03:04

Willem Van Onsem