🐛 Fix objects with pk 0

This commit is contained in:
Yohann D'ANELLO 2020-08-03 10:50:55 +02:00
parent 0e3c4fcaf6
commit 0e8174aacd
1 changed files with 19 additions and 11 deletions

View File

@ -4,12 +4,15 @@
import functools import functools
import json import json
import operator import operator
from copy import copy
from time import sleep from time import sleep
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.mail import mail_admins
from django.db import models from django.db import models
from django.db.models import F, Q, Model from django.db.models import F, Q, Model
from django.forms import model_to_dict
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -38,35 +41,40 @@ class InstancedPermission:
if permission_type == self.type: if permission_type == self.type:
self.update_query() self.update_query()
# Don't increase indexes, if the primary key is an AutoField obj = copy(obj)
if not hasattr(obj, "pk") or not obj.pk:
obj.pk = 0 obj.pk = 0
oldpk = None
else:
oldpk = obj.pk
# Ensure previous models are deleted # Ensure previous models are deleted
for ignored in range(1000): for ignored in range(1000):
if self.model.model_class().objects.filter(pk=obj.pk).exists(): if self.model.model_class().objects.filter(pk=0).exists():
# If the object exists, that means that one permission is currently checked. # If the object exists, that means that one permission is currently checked.
# We wait before the other permission, at most 1 second. # We wait before the other permission, at most 1 second.
sleep(0.001) sleep(0.001)
continue continue
break break
for o in self.model.model_class().objects.filter(pk=obj.pk).all(): for o in self.model.model_class().objects.filter(pk=0).all():
o._force_delete = True o._force_delete = True
Model.delete(o) Model.delete(o)
# An object with pk 0 wouldn't deleted. That's not normal, we alert admins.
msg = "Lors de la vérification d'une permission d'ajout, un objet de clé primaire nulle était "\
"encore présent.\n"\
"Type de permission : " + self.type + "\n"\
"Modèle : " + str(self.model) + "\n"\
"Objet trouvé : " + str(model_to_dict(o)) + "\n\n"\
"--\nLe BDE"
mail_admins("[Note Kfet] Un objet a été supprimé de force", msg)
# Force insertion, no data verification, no trigger # Force insertion, no data verification, no trigger
obj._force_save = True obj._force_save = True
Model.save(obj, force_insert=True) Model.save(obj, force_insert=True)
# We don't want log anything # We don't want log anything
obj._no_log = True obj._no_log = True
ret = self.model.model_class().objects.filter(self.query & Q(pk=obj.pk)).exists() ret = self.model.model_class().objects.filter(self.query & Q(pk=0)).exists()
# Delete testing object # Delete testing object
obj._force_delete = True obj._force_delete = True
Model.delete(obj) Model.delete(obj)
# If the primary key was specified, we restore it with open("/tmp/log", "w") as f:
obj.pk = oldpk f.write(str(obj) + ", " + str(obj.pk) + ", " + str(self.model.model_class().objects.filter(pk=0).exists()))
return ret return ret
if permission_type == self.type: if permission_type == self.type: