How to Update value of a Model with another Model's value in Django

Question:

class Trade(models.Model):
    pips = models.FloatField(default=0)
    direction = models.CharField(max_length=30)
    new_balance = FloatField(default=0.0)
...

class Summary(models.Model):
    winning_trades = models.IntegerField(default=0)
    account_balance = FloatField(default=0.0)
...

When a user post a request he/she will populate the Trade model, this will update the summary model and send back to the user new summary data. How can I do this in an elegant way?

Answers:

First, I will encourage you to create a transaction to perform these two actions. If the second one fails, your database will remain consistent.

Then, Django allows you to override the model methods such as save. You should try that with something like the following:

class Trade():
  ...
  def save(self, *args, **kwargs):
    with transaction.atomic():
      super.save()
      update_summary()

Then, in the view, you could query for the recently updated Summary and return it.

class TradeViewSet():
  def create(self, request, *args, **kwargs):
    user = request.user
    trade = Trade.create(request.data)
    updated_summary = get_summary(user.id)
    response = SummarySerializer(updated_summary)
    return Response(response)
Answered By: Jope Algorta

You’re most likely looking for Django Signals. You’d want your Trade model’s create event to trigger a post_save signal that a listener will receive and process.

Assuming you have saved your models in a file models.py,

Create a file signals.py with the following:


# code
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Trade, Summary
 
 
@receiver(post_save, sender=Trade)
def update_summary(sender, instance, created, **kwargs):
    if created:
        # query to update Summary as needed

You’ll have to add the signals to your app config.

in your apps.py of the relevant app, add the following:

from django.apps import AppConfig
 
class AppnameConfig(AppConfig):
    name = 'appname'
 
    **def ready(self):
        import appname.signals**
Answered By: xprilion
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.