1

I am new to Django and still learning. I am looking to keep track of how many events I have under a test. My current model looks like

class Test(models.Model):
    name = models.CharField(max_length=255)
    description = models.CharField(max_length=255, blank=True)
    num_of_events = models.IntegerField(default=0)

    class Meta:
        verbose_name = 'Test'
        verbose_name_plural = 'Tests'

    def __str__(self):
        return self.name


class Event(models.Model):
    name = models.CharField(max_length=255)
    test = models.ForeignKey(Test,on_delete=models.CASCADE)

    class Meta:
        verbose_name = 'Event'
        verbose_name_plural = 'Events'

    def __str__(self):
        return self.name

    def save(self):
        obj, created = Test.objects.update_or_create(name=self.test)
        obj.num_of_events += 1
        super().save()

    def delete(self):
        self.test.num_of_events -= 1
        super().delete()

I thought I could just override the save() function but it does not update on the admin panel and still shows 0.

I am trying to figure out what I am doing wrong.

EDIT: admin.py

class TestAdmin(admin.ModelAdmin):
    list_display = ('name', 'description', 'num_of_events')

    fieldsets = [
        (None, {'fields': ('name', 'description')})
    ]

class EventsAdmin(admin.ModelAdmin):
    pass

class PropertyAdmin(admin.ModelAdmin):
    list_display = ('name', 'property_type', 'expected_value')

admin.site.register(Test, TestAdmin)
admin.site.register(Event, EventsAdmin)
admin.site.register(Property, PropertyAdmin)
Halloween
  • 388
  • 3
  • 15

1 Answers1

0

You forget to save the Test object. For example with:

class Event(models.Model):
    # …

    def save(self):
        if self.test_id is not None:
            obj = self.test
            obj.num_of_events += 1
            obj.save()
        super().save()

    def delete(self):
        if self.test_id is not None:
            self.test.num_of_events -= 1
            self.test.save()
        super().delete()

But regardless, storing the number of items is usually not a good idea. Say that you change the .test of a given Event, then you need to subtract from the old Test and add to the new Test. Furthermore ORM operations in bulk, like .update(..) circumvent .save() and signals, so it will be hard or impossible to keep this correct.

The point is that you do not need to store the number of Events. Indeed, you can simply obtain these with:

from django.db.models import Count

Test.objects.annotate(number_of_events=Count('event'))

The Test objects that arise from this queryset will have an extra attribute .number_of_events that contains the number of related Event ojbects.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555