Ich möchte einen Fremdschlüsselwert ändern, wenn er aus der Datenbank gelöscht wird. Also schaute ich auf das Dokument und verwendete die Methode on_delete = models.SET (foo). https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.SETDjango pass self to models.SET on_delete
Das ist meine Bestimmung des Modells
class OrderLine(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET(getDuplicateProduct), null=True)
quantity = models.PositiveSmallIntegerField(default=1)
finalPricePerUnit = models.PositiveIntegerField()
order = models.ForeignKey(Order, on_delete=models.PROTECT)
dateCreated = models.DateTimeField(auto_now=False, auto_now_add=True)
Und das ist meine Methode, die auf Lösch
def getDuplicateProduct(orderline):
productToDelete = orderline.product
# some logic to generate duplicate copy and returning it
genannt wird, aber hier ist das Problem, dass ich nicht Argument dieser Methode passieren kann die Deshalb kann ich nicht wissen, welches Produkt gelöscht wurde. Ich habe auch versucht, Signale wie in dieser Antwort django model on_delete pass self to models.SET()
Ich habe auch versucht, mit Signalen, aber das hat auch nicht funktioniert. Ich kann keine passende Lösung dafür finden. Lassen Sie mich wissen, wenn jemand eine Idee hat, wie dies zu erreichen ist.
EDIT
Dies ist der Code, den ich in Signale mit am
@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
product = kwargs['instance']
orderlines = product.orderline_set.all()
#further processing
Das Problem ist jetzt, dass django meine Auftragszeilen als auch zu löschen versucht (als Standard on_delete auf Kaskade eingestellt ist). Und wenn ich on_Delete auf SET_NULL setze, setzt es den Fremdschlüssel auf null.
EDIT -2 Hier ist der Code ich für Vollständigkeit
@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
product = kwargs['instance']
orderlines = product.orderline_set.all()
product.name = product.name + ' ' + product.get_type_display()
newProduct = deepcopy(product)
newProduct.name = product.name + ' ' + product.get_type_display()
newProduct.pk=None
newProduct.id=None
newProduct.save()
product.duplicateProductId = newProduct.id
product.old_orderlines = orderlines
product.save()
@receiver(post_delete, sender=Product)
def handlePostDelete(sender, **kwargs):
product = kwargs['instance']
newProduct = Product.objects.get(id=product.duplicateProductId)
for orderline in product.old_orderlines:
orderline.product = newProduct
orderline.save()
EDIT-3 Veröffentlichung vollständige Umsetzung verwenden.
@receiver(pre_delete, sender=Product)
def handlePreDelete(sender, **kwargs):
product = kwargs['instance']
orderlines = product.orderline_set.all()
shouldCreate=False
for orderline in orderlines:
if orderline.order.status>1:
shouldCreate=True
product.shouldCreate = shouldCreate
if shouldCreate:
product.old_orderlines = orderlines
product.save()
else:
product.save()
return None
@receiver(post_delete, sender=Product)
def handlePostDelete(sender, **kwargs):
product = kwargs['instance']
shouldCreate = product.shouldCreate
if shouldCreate:
newProduct = deepcopy(product)
newProduct.name = product.name + ' ' + product.get_type_display()
newProduct.pk=None
newProduct.id=None
newProduct.save()
# Do whatever you want with product.old_orderlines
for orderline in product.old_orderlines:
orderline.product = newProduct
orderline.save()
"Ich habe keine Referenz der Bestellnummer in Receiver-Methode.". Warum nicht? Können Sie den Code, den Sie mit Signalen verwendet haben, posten? – solarissmoke
In Ihrer zweiten Bearbeitung, denke ich, ist es die 'Deepcopy', die das Problem verursacht. Sehen Sie, ob Sie das in den 'post_delete'-Handler verschieben können. Außerdem müssen Sie das Abfrageset kopieren, um zu vermeiden, dass es verpatzt wird (ich habe meine Antwort unten bearbeitet). – solarissmoke
@solarissmoke Ich habe versucht, tiefe Kopie zu post_delete Handler zu verschieben und es scheint zu funktionieren, danke und Entschuldigung für die späte Antwort, ging aus der Stadt für 10 Tage. – Anurag