【问题标题】:Django update number of items on each save or deleteDjango在每次保存或删除时更新项目数
【发布时间】:2020-04-16 18:39:44
【问题描述】:

我是 Django 新手,还在学习。我希望跟踪我有多少 events 正在接受测试。我现在的模型看起来像

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()

我以为我可以重写 save() 函数,但它没有在管理面板上更新并且仍然显示 0。

我想弄清楚我做错了什么。

编辑: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)

【问题讨论】:

  • 请不要存储商品数量。您可以使用 annotate 来获取每个 TestEvents 的数量。这个比较靠谱。
  • 你做错的是not保存Test对象,但无论如何,data duplicationnot好主意。

标签: django django-models


【解决方案1】:

您忘记保存Test 对象。例如:

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()

但无论如何,存储项目的数量通常不是一个好主意。假设您更改了给定Event.test,那么您需要从旧的Test 中减去并添加到新的Test。此外,批量 ORM 操作,如 .update(..) 规避 .save() 和信号,因此很难或不可能保持正确。

关键是您不需要需要存储Events 的数量。事实上,您可以通过以下方式简单地获得这些:

from django.db.models import Count

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

this 查询集产生的Test 对象将有一个额外的属性.number_of_events,其中包含相关Event ojbect 的数量。

【讨论】:

  • 我应该把那条线放在哪里?
  • @Halloween:在您需要事件数量或需要过滤事件数量的视图中。
  • 它在管理页面中。我正在使用 list_display 打印出面板中的变量。
  • @Halloween:您可以覆盖ModelAdminget_queryset 以显示注释:stackoverflow.com/a/48607830/67579
  • 我将我的 admin.py 添加到问题中。我会把它放在 EventsAdmin 函数中吗?
猜你喜欢
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
  • 2018-04-04
  • 2011-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多