Django默认可调用引用模型的另一个字段

时间:2016-11-23 10:42:00

标签: django python-3.x django-models

我有一个代表书页的模型。

class BookPage(models.Model):

def getMaximumPageNumber():
    page_numbers = (i.page_number for i in BookPage.objects.all())
    return max(page_numbers)+1

page_number = models.IntegerField(default=getMaximumPageNumber, validators=[MinValueValidator(1)])
book = models.ForeignKey('Book', on_delete=models.CASCADE)


  //other stuff

我希望Django在创建时自动分配页码,因此我制作了getMaximumPageNumber()。如果我只有一本书,那就行得很好。但现在我想从这个函数中引用book,所以它就像page_numbers = (i.page_number for i in BookPage.objects.filter(book=self.book)。但问题是我似乎无法在此函数中使用self,因为如果我将其指定为def getMaximumPageNumber(self):,那么当我尝试访问时它会显示TypeError: getMaximumPageNumber() missing 1 required positional argument: 'self'在管理员中添加页面屏幕。因此我无法指定我想要找到最大页面的书,这就是我真正需要在这里完成的。

有没有办法从默认分配函数引用新创建的模型实例的另一个字段?我最初的解决方案是覆盖此模型的save(),但它打破了我已经写过的其他一些事情,因此使用动态"默认"如果在我的情况下可能会更好。

2 个答案:

答案 0 :(得分:1)

首先,应该更新最大页面计算方法。通过重写Django模型save()方法可以实现这样的要求:

from django.db.models import Max

class BookPage(models.Model):
    page_number = models.IntegerField(default=getMaximumPageNumber, validators=[MinValueValidator(1)])
    book = models.ForeignKey('Book', on_delete=models.CASCADE)

    def save(self, *args, **kwargs):

        queryset = BookPage.objects.filter(book=self.book).aggregate(Max('page_number'))
        max_page = queryset['page_number__max']
        self.page_number =  max_page +1
        super(BookPage, self).save(*args, **kwargs)

答案 1 :(得分:0)

在管理模型中覆盖save_model更容易。并且它不会导致覆盖模型save()

的损坏
def save_model(self, request, obj, form, change):
    max_page = BookPage.objects.filter(book=obj.book).aggregate(Max('page_number'))['page_number__max']
    obj.page_number = max_page + 1
    obj.save()

向Prakhar Trivedi致敬reminder about aggregations