Как обновить значение модели с помощью значения другой модели в Django
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)
...
Когда пользователь публикует запрос, он/она заполняет торговую модель, это обновляет сводную модель и отправляет обратно пользователю новые сводные данные. Как я могу сделать это элегантным способом?
Во-первых, я посоветую вам создать транзакцию для выполнения этих двух действий. Если второе не удастся, ваша база данных останется последовательной.
Тогда Django позволяет вам переопределить методы модели, такие как save
. Вы должны попробовать сделать это с помощью чего-то вроде следующего:
class Trade():
...
def save(self, *args, **kwargs):
with transaction.atomic():
super.save()
update_summary()
Затем, в представлении, вы можете запросить недавно обновленный Summary
и вернуть его.
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)
Надеюсь, это поможет вам.
Вы, скорее всего, ищете Django Signals. Вы хотите, чтобы событие Trade
вашей модели create
вызывало post_save
сигнал, который слушатель получит и обработает.
Предположим, что вы сохранили свои модели в файл models.py
,
Создайте файл signals.py
со следующим:
# 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
Вам придется добавить сигналы в конфигурацию вашего приложения.
в вашем apps.py
соответствующем приложении добавьте следующее:
from django.apps import AppConfig
class AppnameConfig(AppConfig):
name = 'appname'
**def ready(self):
import appname.signals**