2016-01-31 2 views
3

Я пытаюсь добавить все значения total в модель Transaction и поместить их в поле ввода Sale (pk=1) gross_total. Вот мой код.Как обновить поле модели, основанное на обновлении поля другой модели с помощью сигналов?

models.py

class Sale(models.Model): 
    gross_total = models.FloatField() 

    def __unicode__(self): 
     return str(self.gross_total) 

class Transaction(models.Model): 
    sale = models.ForeignKey('Sale') 
    price = models.FloatField() 
    quantity = models.IntegerField() 
    total = models.FloatField(blank=True, null=True) 

    def save(self): 
     self.total = self.price * self.quantity 
     return super(Transaction, self).save() 

    def __unicode__(self): 
     return str(self.total) 

signals.py

from django.db.models.signals import post_save 
from django.dispatch import receiver 
from django.db.models import Sum 

from .models import Transaction, Sale 

@receiver(post_save, sender=Transaction) 
def update_sale(sender, **kwargs): 
    sale = Sale.objects.get(pk=1) 
    sale.gross_total = Transaction.objects.all().aggregate(Sum('total'))['total__sum'] 
    sale.save() 

Я новичок в использовании Django сигналов. Что я делаю неправильно? Если я сохраню экземпляр модели Transaction, данные модели Sale не обновляются!

+0

Вы импортировали функцию 'signals.py' в' ready() 'в свой AppConfig, как предложено в разделе« Где должен находиться этот код? ». в документах https://docs.djangoproject.com/en/1.9/topics/signals/#connecting-receiver-functions? – Nikita

+0

@ Никита Я этого не делал. Я прочитал главу сигналов в документации, но мне это не очень понятно. Можете ли вы помочь в этом отношении? – MiniGunnR

+0

@Nikita Ok Я получил это, чтобы работать с копированием кодов из другого блога, но я понятия не имею, как это работает! Можете ли вы предложить мне легкий материал для чтения? – MiniGunnR

ответ

2

Я внесла следующие изменения в свое приложение, чтобы заставить его работать.

__init__.py

default_app_config = 'alpha.apps.MyAppConfig' 

Теперь создайте apps.py внутри моего приложения.

apps.py

from django.apps import AppConfig 

class MyAppConfig(AppConfig): 
    name = 'alpha' 
    verbose_name = 'Alpha' 

    def ready(self): 
     import alpha.signals 

Я не имею ни малейшего представления, как все это работает, хотя, лол.

3

Что происходит ...

Когда вы пишете код в signals.py это правильный код, но он никогда не работать, до тех пор пока этот модуль выполняется непосредственно (не предназначению, хотя в данном случае) или импортного производства. Поэтому он должен быть импортирован где-то для запуска кода и регистрации функций обработчика соответствующим сигналам.

Когда проект Django запущен, Django создает реестр приложений из приложений, указанных в вашем settings.py. При создании реестра он импортирует каждый пакет и модуль, объявленный в settings.py, а также вызывает несколько предопределенных функций во время этого процесса, включая ready() внутри каждого AppConfig.

При импорте пакета в Python код внутри специального файла __init__.py выполняется автоматически с помощью внутренних компонентов Python, как правило, он позволяет определять особые свойства и свойства для пакета.

Так поясню, это приводит к:

  1. проект Django запускается.

  2. Django читает settings.py и находит ваше приложение в качестве одного из объявленных.

  3. Django импортирует ваш пакет приложений, код внутри __init__.py запущен и указан default_app_config. Теперь Дганго это знает.

  4. Когда обработка всех приложений завершена, Django вызывает функцию ready() на каждые AppConfig, обнаруженные во время предыдущих шагов.

  5. ready() в MyAppConfig запущен, и ваш модуль signals.py импортируется.

  6. Во время этого импорта выполняется код внутри signals.py: ваша функция update_sale создана, и @receiver decorator выполняется с ней как аргумент.

  7. receiver декоратора код в то же время выполняются регистры update_sale функцию, которая будет выполняться на post_save сигнала, излучаемого Transaction класса модели.

Смежные вопросы