I have the following code in a unit test:
serum_sample.msruns.all().delete()
print(f"THIS SHOULD BE 0: {serum_sample.msruns.count()}")
serum_sample.delete()
I get out:
THIS SHOULD BE 0: 0
In the code, I've deleted the related records that have the RESTRICT relationship, but I still get this error:
django.db.models.deletion.RestrictedError: ("Cannot delete some instances of model 'Sample' because they are referenced through restricted foreign keys: 'MSRun.sample'.", {<MSRun: MS run of sample BAT-xz971 with Default by anonymous on 2021-04-29>, <MSRun: MS ...
The relation is:
class MSRun(HierCachedModel, MaintainedModel):
...
sample = models.ForeignKey(
to="DataRepo.Sample",
on_delete=models.RESTRICT,
related_name="msruns",
help_text="The sample that was run on the mass spectrometer.",
)
I thought that to be able to delete the sample, all I had to do was delete the MSRun records that link to it...
Why would this not be the case?
UPDATE
I previously deleted this question because I thought I'd tracked it down, but apparently not, so I am adding some more insights/context.
My hunch was in relation to the 2 databases we have: default and validation. (The validation database exists to validate user data submissions and should not be used in the context of this test.)
I'd successfully executed the delete in the validation database explicitly, which is what made me think that maybe I had some cross database foreign keys, but it turned out that it actually worked because there existed no Sample or MSRun records in the validation database (as should be the case). So for context, in the shell:
In [21]: Sample.objects.using("validation").last()
In [22]: Sample.objects.using("default").last()
Out[22]: <Sample: serum-xz971>
In [42]: MSRun.objects.using("default").all()
Out[42]: <QuerySet [<MSRun: MS run of sample BAT-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Br-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Dia-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample H-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Kid-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Liv-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Lu-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Pc-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Q-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample SI-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Sol-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample Sp-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample gWAT-xz971 with Default by Anonymous on 2021-06-03>, <MSRun: MS run of sample gas-xz971 with Default by Anonymous on 2021-06-03>]>
In [43]: MSRun.objects.using("validation").all()
Out[43]: <QuerySet []>
The other thing is the parent classes: HierCachedModel and MaintainedModel. The tests worked under HierCachedModel, and they were working on my previous branch that added MaintainedModel. But in my current branch, I added the ability to propagate changes to maintained fields in related child models. Previously, it only propagated changes to parent model records (without issue).
I am now assuming that something is awry with the propagation of child model objects, which occur in a DFS order.
Both HierChachedModel and MaintainedModel override .delete():
class MaintainedModel(Model):
...
def delete(self, *args, **kwargs):
propagate = kwargs.pop("propagate", True)
super().delete(*args, **kwargs)
if auto_updates is False:
self.buffer_parent_update()
return
if propagate:
self.call_dfs_related_updaters()
class HierCachedModel(Model):
...
def delete(self, *args, **kwargs):
if caching_updates:
self.delete_related_caches()
super().delete(*args, **kwargs)
I have tried calling delete with propagate=False -> same exception.
The propagation of updates simply calls save() on all referenced model objects via foreign keys, following the hierarchy. But nowhere in that code is delete() called, so I am confounded as to why the exception mentions all those MSRun records that link to different samples other than the one I'm deleting (serum-xz971).
Similarly, with HierCachedModel, it deletes caches along the hierarchy from the root down the hierarchical tree.