Django unittest on_delete CASCADE

Viewed 439

I am writing tests for a Django application.

Currently, to test for the cascade deletion, I create instances, delete the parent and assert the child is deleted as well.

Is there a better method to do this, for example retrieve the parameters passed to the ForeignKey of the model using _meta.get_field ?

2 Answers

You can get a list of fields from a model with Model._meta.get_fields(). Then for each field, you can chck if it is a ForeignKey (or OneToOneField, which is a subclass of a ForeignKey) with isinstance(field, ForeignKey), and then obtain the attribute field.on_delete to determine what the "parent" will do with the "child" if it is deleted.

So you can for example obtain the names of the fields for which the ForeignKey is set to CASCADE with:

[f.name
 for f in MyModel._meta.get_fields()
 if isinstance(f, ForeignKey) and f.remote_field.on_delete is models.CASCADE]

Here's @Willem's answer rewritten as a test function with verbose failure:

def test_foreignkey_cascade(self):
    """
    Test all FKs have on_delete=models.CASCADE unless otherwise specified
    """

    for f in self.model_instance._meta.get_fields():
        if isinstance(f, models.ForeignKey):
            self.assertEquals(f.remote_field.on_delete, models.CASCADE,
                              '{} failed, value was {}'.format(
                                  f.name, f.remote_field.on_delete))
Related