So, I have a post_save signal using the @receiver decorator. It “looks” like it’s getting called twice. I don’t see where I could be committing the data twice.
I’m using the signal to make an “Activity Log”. In this case, it’s my model “Batch” and “addBatch()” view.
models.py (snipped):
class Batch(models.Model):
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'batches'
name = models.CharField(max_length=50)
startdate = models.DateTimeField(auto_now=True)
enddate = models.DateTimeField(null=True, blank=True)
lotId = models.CharField(max_length=7, null=True) # Bottledate L[2digityear][0paddedYearDays] = L22088
#size = models.IntegerField()
#size_units = models.ForeignKey(Unit, on_delete=models.SET("_del"))
size = DescriptiveQuantityField(base_units='liters', unit_choices=['liters','gallons'])
active = models.BooleanField(default=True)
# Using the 'related_name' on batches, applies that name on the other side for "Fermenter.batch"
#fermenter = models.ManyToManyField(Fermenter, blank=True, related_name='batch')
fermenter = models.ForeignKey(Fermenter, on_delete=models.RESTRICT)
startingGravity = QuantityField(base_units="sg")
estimatedEndGravity = QuantityField(base_units="sg")
#category = models.ForeignKey(BatchCategory, on_delete=models.SET("_del"), blank=True, null=True)
category = models.ForeignKey(BatchCategory, on_delete=models.RESTRICT, blank=True, null=True)
#activity = models.ManyToManyField(ActivityLog, blank=True, related_name='batch')
activity = models.ManyToManyField(ActivityLog, blank=True, related_name='batch')
#recipe = models.ForeignKey(Recipe, on_delete=models.SET("_del"), null=True, blank=True)
recipe = models.ForeignKey(Recipe, on_delete=models.RESTRICT, null=True, blank=True)
# TODO Add additional objects
aging_vessel = None
packaging = None
def transfer(self,src_vessel, dst_vessel):
pass
def complete(self):
self.enddate = datetime.now()
self.active = False
def current_gravity(self):
gravity_tests = self.tests.filter(type__shortid='specific-gravity')
if len(gravity_tests) > 1:
return gravity_tests.last().value
return gravity_tests[0].value
def percent_complete(self):
est_fg = self.estimatedEndGravity.magnitude
current_gravity = self.current_gravity()
return round((self.startingGravity.magnitude - current_gravity) / (self.startingGravity.magnitude - est_fg) * 100)
# If a batch is saved with a Starting Gravity, add that test
@receiver(post_save,sender=Batch)
def addGravityTest(sender,instance,**kwargs):
print("Adding Gravity")
if instance.startingGravity:
gravTest = BatchTest()
testType = BatchTestType.objects.filter(shortid='specific-gravity')[0]
gravTest.type = testType
gravTest.value = instance.startingGravity
gravTest.description = "Auto created from new batch."
gravTest.datetime = datetime.now()
unit = Unit.objects.filter(name__contains="specific")[0]
gravTest.units = unit
gravTest.batch = instance
print("Saving gravity")
gravTest.save()
@receiver(post_save,sender=BatchNote)
@receiver(post_save,sender=BatchAddition)
@receiver(post_save,sender=BatchTest)
@receiver(post_save,sender=Batch)
def addActivity(sender,instance,created=False,**kwargs):
text = None
batch = None
date = datetime.now()
if sender.__name__ == "Batch":
batch = instance
if created:
text = "Batch Created"
else:
text = "Batch Modified"
if sender.__name__ == "BatchNote":
batch = instance.batch
if created:
text = "Added ["+instance.notetype.name+"] :: " + instance.text
if sender.__name__ == "BatchAddition":
batch = instance.batch
if created:
text = "Added [" + instance.name.name + "] :: " + str(instance.amount) + " " + instance.units.name
else:
text = "Updated [" + instance.name.name + "]"
if sender.__name__ == "BatchTest":
batch = instance.batch
if created:
text = "Added [" + instance.type.name + "] :: " + str(instance.value) + " " + instance.units.name
else:
text = "Updated [" + instance.type.name + "]"
if text:
log = ActivityLog(datetime=date,text=text)
log.save()
batch.activity.add(log)
views.py (snipped):
def addBatch(request, pk=None):
if request.method == "POST":
form = BatchAddForm(request.POST)
if form.is_valid():
batch = Batch()
batch.name = form.cleaned_data['name']
batch.startdate = form.cleaned_data['startdate']
batch.size = form.cleaned_data['size']
#size_unit = Unit.objects.filter(pk=form.cleaned_data['size_units'])[0]
#batch.size_units = size_unit
batch.startingGravity = form.cleaned_data['startingGravity']
batch.estimatedEndGravity = form.cleaned_data['estimatedEndGravity']
batch.fermenter = form.cleaned_data['fermenter']
newbatch = batch.save()
#fermenters = form.cleaned_data['fermenter']
batch.recipe = form.cleaned_data['recipe']
#for fermenter in fermenters:
# batch.fermenter.add(fermenter)
batch.save()
return HttpResponseRedirect(reverse('batch', kwargs={'pk': batch.pk}))
else:
return render(request, template_name='batchthis/addBatch.html', context={'form': form})
else:
if pk:
batch = Batch.objects.get(pk=pk)
form = BatchAddForm(initial=model_to_dict(batch))
form.fermenter = batch.fermenter
else:
form = BatchAddForm()
form.fields['fermenter'].queryset = Fermenter.objects.filter(vessel__status=Vessel.STATUS_READY)
return render(request, "batchthis/addBatch.html", {'form': form})
Activity Log:
2025-02-22 18:47 PM: Added [Specific Gravity] :: 1.108 Specific Gravity
2025-02-22 18:47 PM: Batch Created
2025-02-22 18:47 PM: Added [Specific Gravity] :: 1.108 Specific Gravity
2025-02-22 18:47 PM: Batch Modified
I’m a little confused. Anyone have thoughts?