Questo sarebbe avvolgere soluzione dall'implementazione nella mia app.Qualche codice è forma LWN's answer.
Ci sono 4 le situazioni che i dati vengono cancellati:
- query SQL
- Calling
delete()
su istanza modello: project.delete()
- Calling
delete()
su QuerySet innstance: Project.objects.all().delete()
- Eliminato dal campo ForeignKey su altro Modello
Mentre non c'è nulla che puoi fare con il primo caso, gli altri tre possono essere controllati a grana fine. Un consiglio è che, nella maggior parte dei casi, non si dovrebbero mai cancellare i dati stessi, poiché tali dati riflettono la cronologia e l'utilizzo della nostra applicazione. Impostazione su active
Il campo booleano viene invece preferito.
Per evitare delete()
su istanza del modello, sottoclasse delete()
nella dichiarazione Modello:
def delete(self):
self.active = False
self.save(update_fields=('active',))
Mentre delete()
su istanza QuerySet ha bisogno di un po 'di messa a punto con un gestore di oggetto personalizzato come in LWN's answer.
Wrap questo fino a un'implementazione riutilizzabile:
class ActiveQuerySet(models.QuerySet):
def delete(self):
self.save(update_fields=('active',))
class ActiveManager(models.Manager):
def active(self):
return self.model.objects.filter(active=True)
def get_queryset(self):
return ActiveQuerySet(self.model, using=self._db)
class ActiveModel(models.Model):
""" Use `active` state of model instead of delete it
"""
active = models.BooleanField(default=True, editable=False)
class Meta:
abstract = True
def delete(self):
self.active = False
self.save()
objects = ActiveManager()
Uso, solo su bclass ActiveModel
classe:
class Project(ActiveModel):
...
Comunque il nostro oggetto può ancora essere cancellato se uno qualsiasi dei suoi campi ForeignKey vengono eliminati:
class Employee(models.Model):
name = models.CharField(name, unique=True)
class Project(models.Model):
name = models.CharField(name, unique=True)
manager = purchaser = models.ForeignKey(
Employee, related_name='project_as_manager')
>>> manager.delete() # this would cause `project` deleted as well
Questo può essere prevenuta con l'aggiunta di on_delete argument di campo Modello:
class Project(models.Model):
name = models.CharField(name, unique=True)
manager = purchaser = models.ForeignKey(
Employee, related_name='project_as_manager',
on_delete=models.PROTECT)
L'impostazione predefinita di on_delete
è CASCADE
che causerà l'eliminazione dell'istanza utilizzando PROTECT
invece che genererà un ProtectedError
(una sottoclasse di IntegrityError
). Un altro scopo di questo è che la ForeignKey dei dati dovrebbe essere tenuta come riferimento.
Questo non è possibile solo utilizzando il codice Python; anche il database stesso dovrà essere modificato. –
Grazie per il tuo commento. Sto cercando prima la parte Python/Django e vedo quanto mi arriva nella mia app. – dyve