Django обновляет связанные объекты при сохранении с помощью сигналов

Я столкнулся с проблемой, которую не могу решить.

Я создал простую многошаговую форму, чтобы помочь пользователю создать проект.

Краткое пояснение: Проект - это основная модель ProjectDetails добавляют информацию к проекту. В одном проекте может быть 'n' ProjectDetails. Каждая деталь включает в себя сделку, которая является внешним ключом ProjectDetails. Для каждого ProjectDetail может быть только одна сделка

class Trade(models.Model): 
    ...
    shipped_quantity = models.IntegerField(default=0)
    status = models.IntegerField(
        choices=Status.choices,
        default=Status.CREATED
    )

class Project(models.Model):
    ...
    quantity = models.IntegerField(default=0)
    status = models.IntegerField(
        choices=Status.choices,
        default=Status.INIT
    )

class ProjectDetail(models.Model):

    project = models.ForeignKey(Project, on_delete=models.CASCADE, default='', blank=True, null=True,
                              related_name='details')
    trade = models.ForeignKey(Trade, on_delete=models.SET_NULL, default='', blank=True, null=True,
                              related_name='project')
    quantity = models.IntegerField()

После того, как пользователь выполнил последний шаг и завершил создание проекта, я хотел бы обновить некоторые связанные поля: a) суммировать количество всех сделок и обновить количество проекта b) обновить для каждой сделки отгруженное_количество c) обновить статус каждой сделки

Вот мой код view.py:

def project_create_complete(request, *args, **kwargs):
    # Final step to complete the project creation
    # update the status to SAVED and delete the session
    if request.POST:
        project = Project.objects.get(id=request.POST['project_id'])
        if project.status < Project.Status.SAVED:
            project.status = Project.Status.SAVED
        project.transaction_number = get_transaction_number()

        # Getting the total quantity of the project
        import_quantity = ProjectDetail.objects.filter(project=project, trade__category=Trade.TradeType.BUY).aggregate(tot=Sum('quantity'))
        export_quantity = ProjectDetail.objects.filter(project=project, trade__category=Trade.TradeType.SELL).aggregate(tot=Sum('quantity'))
        total_quantity = max(import_quantity['tot'], export_quantity['tot'])
        project.quantity = total_quantity

        # Update the shipped quantity to the Trade
        trades = ProjectDetail.objects.filter(project=project)
        # For every trade associated to the project
        for trade in trades:
            # Check if the quantity of the project is equal to the quantity of the trade
            if trade.quantity == trade.trade.quantity:
                # If yes, trade is fully completed
                trade.trade.status = Trade.Status.COMPLETED
            else:
                # If no, trade is still open
                trade.trade.status = Trade.Status.OPEN
            # Update the quantity shipped to the trade
            trade.trade.shipped_quantity = trade.quantity
            # Add the project to the trade, this is necessary when a trade is split in more than one project
            if trade.trade.projects:
                # Create the list of projects
                projects = trade.trade.projects.split(',')
                # Append the new project to the list
                projects.append(project.transaction_number)
                # Transfer the list to string and update it to the project
                trade.trade.projects = ','.join(projects)
            else:
                trade.trade.projects = project.transaction_number
            trade.trade.save()

        project.save()

        # Delete the session
        try:
            del request.session['new_project']
            del request.session['matching']
        except KeyError:
            pass
        messages.success(request, f'{project.reference} ({project.transaction_number}) has been created successfully')
        return redirect('trading:view_trades')
    return redirect('trading:project-create-4')

Функция отлично работает и создает проект, обновляет значение в нем и обновляет объект, связанный с торговлей.

Поскольку я также хотел бы улучшить свой код, я думал реализовать 'сохранение' с помощью сигналов. Это глупая идея? Единственная проблема, которую я вижу, заключается в том, что форма работает со следующими шагами:

  1. User initiate the Project and save an empty Project
  2. Add a Trade to ProjectDetail. ProjectDetail can be 'n' linked to Project
  3. Review the details attached to the Project
  4. Confirm the Project and the code update all the status (this allow the admin to delete any incomplete Project)

Поэтому я не знаю, как связать сигнал со вторым save_project, а не с первым.

Есть ли другое решение, которое я мог бы рассмотреть для улучшения моего кода?

Надеюсь, мои объяснения достаточно понятны, чтобы получить обратную связь. Заранее спасибо

Вернуться на верх