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')
Функция отлично работает и создает проект, обновляет значение в нем и обновляет объект, связанный с торговлей.
Поскольку я также хотел бы улучшить свой код, я думал реализовать 'сохранение' с помощью сигналов. Это глупая идея? Единственная проблема, которую я вижу, заключается в том, что форма работает со следующими шагами:
- User initiate the Project and save an empty Project
- Add a Trade to ProjectDetail. ProjectDetail can be 'n' linked to Project
- Review the details attached to the Project
- Confirm the Project and the code update all the status (this allow the admin to delete any incomplete Project)
Поэтому я не знаю, как связать сигнал со вторым save_project
, а не с первым.
Есть ли другое решение, которое я мог бы рассмотреть для улучшения моего кода?
Надеюсь, мои объяснения достаточно понятны, чтобы получить обратную связь. Заранее спасибо