Ich habe eine Frage zu Django.
Ich habe ManyToMany Modelle hier
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(default=0.0, max_digits=9, decimal_places=2)
stock = models.IntegerField(default=0)
def __unicode__(self):
return self.name
class Cart(models.Model):
customer = models.ForeignKey(Customer)
products = models.ManyToManyField(Product, through='TransactionDetail')
t_date = models.DateField(default=datetime.now())
t_sum = models.FloatField(default=0.0)
def __unicode__(self):
return str(self.id)
class TransactionDetail(models.Model):
product = models.ForeignKey(Product)
cart = models.ForeignKey(Cart)
amount = models.IntegerField(default=0)
Für 1 erstelltes Warenkorbobjekt kann ich so viele wie neue TransactionDetail-Objekte (das Produkt und die Menge) einfügen. Meine Frage ist. Wie kann ich den Trigger implementieren? Ich möchte, dass bei jeder Erstellung eines Transaktionsdetails der Betrag des Produktbestands durch den Betrag im Transaktionsdetail abgezogen wird.
Ich habe über post_save () gelesen, bin mir aber nicht sicher, wie ich es implementieren soll. vielleicht so etwas
wann:
post_save(TransactionDetail,
Cart) #Cart object where TransactionDetail.cart= Cart.id
Cart.stock -= TransactionDetail.amount
python
django
django-models
django-signals
Haris Hamdani
quelle
quelle
Antworten:
Wenn Sie wirklich Signale verwenden möchten, um dies zu erreichen, erfahren Sie hier kurz, wie:
from django.db.models.signals import post_save from django.dispatch import receiver class TransactionDetail(models.Model): product = models.ForeignKey(Product) # method for updating @receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count") def update_stock(sender, instance, **kwargs): instance.product.stock -= instance.amount instance.product.save()
quelle
maximum recursion depth exceeded
Fehlermeldung, weil ich die Instanz selbst in der@receiver
Funktion gespeichert habe. Wie kann ich Selbstmodelle aktualisieren? Muss ich die Modellmethode überschreibensave()
?signal
I zu verwenden, überschreibe ich diesave
Modellmethode und verwende dieupdated
funktionsaktualisierte Modelleigenschaft, damit das Speichern nicht erneut ausgelöst wird.dispatch_uid
?Persönlich würde ich die save () -Methode von TransactionDetail überschreiben und dort das neue TransactionDetail speichern und dann ausführen
quelle
Wenn Sie das Abrufen vermeiden möchten,
maximum recursion depth exceeded
sollten Sie die Signale trennen , bevor Sie sie im Signalhandler speichern. Das obige Beispiel (Kenny Shens Antwort) wäre dann:from django.db.models.signals import post_save from django.dispatch import receiver class TransactionDetail(models.Model): # ... fields here # method for updating @receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count") def update_stock(sender, instance, **kwargs): instance.product.stock -= instance.amount post_save.disconnect(update_stock, sender=TransactionDetail) instance.product.save() post_save.connect(update_stock, sender=TransactionDetail)
Dies wird ausführlich unter Trennen von Signalen für Modelle und erneutes Verbinden in Django mit einem abstrakteren und nützlicheren Beispiel beschrieben.
Siehe auch: https://docs.djangoproject.com/de/2.0/topics/signals/#disconnecting-signals in den Django-Dokumenten.
quelle
dispatch_uid
die Methodendisconnect
und habenconnect
. Die Rückgabewerte helfen Ihnen beim Umgang mit potenziellen Fehlern. `Is_disconnected = post_save.disconnect (update_stock, sender = TransactionDetail, dispatch_uid = "update_stock_count") , wenn is_diconnected: instance.product.save () is_reconnected = post_save.connect (update_stock, sender = TransactionDetail, dispatch_uid = "update_stock_count")`Wenn Sie wirklich Signale in Django verwenden möchten, versuchen Sie dies bitte:
#import inbuilt user model from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender,**kwargs): # write you functionality pass
Fügen Sie dann default_app_config in die Init-Datei ein
default_app_config = "give your AppConfig path"
quelle
In der Tat erklärt der Dokumentstring das
Signals
ist indjango.dispatch.Signal.connect
:def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): Connect receiver to sender for signal. Arguments: receiver A function or an instance method which is to receive signals. Receivers must be hashable objects. If weak is True, then receiver must be weak referenceable. Receivers must be able to accept keyword arguments. If a receiver is connected with a dispatch_uid argument, it will not be added if another receiver was already connected with that dispatch_uid. sender The sender to which the receiver should respond. Must either be a Python object, or None to receive events from any sender. weak Whether to use weak references to the receiver. By default, the module will attempt to use weak references to the receiver objects. If this parameter is false, then strong references will be used. dispatch_uid An identifier used to uniquely identify a particular instance of a receiver. This will usually be a string, though it may be anything hashable.
quelle