简体   繁体   English

Django模型字段的默认值是否可以由依赖于外部父模型的函数定义?

[英]Can a Django model field's default value be defined by a function dependent on a foreign parent model?

I'm trying to have the default value of Report 's fee be based on a parent model's attributes. 我试图让Report的默认值基于父模型的属性。 I don't want to do this in save() , because the field needs to be presented to the user if they choose to override the value before saving. 我不想在save()执行此操作,因为如果他们选择在保存之前覆盖该值,则需要将该字段呈现给用户。

Here are the three methods I've tried, in addition to passing only function pointers (ie without () ). 以下是我尝试过的三种方法,除了只传递函数指针(即没有() )。 The errors are raised when I run python manage.py shell . 运行python manage.py shell时会出错。

#1
from django.db import models

class Job(models.Model):
    veryImportant = models.IntegerField()
    def get_fee(self):
        return 2 * self.veryImportant

class Report(models.Model):
    job = models.ForeignKey(Job)
    overridableFee = models.DecimalField(default=job.get_fee(), max_digits=7, decimal_places=2)

#gives...
#AttributeError: 'ForeignKey' object has no attribute 'get_fee'

#2
from django.db import models

class Job(models.Model):
    veryImportant = models.IntegerField()

class Report(models.Model):
    job = models.ForeignKey(Job)
    overridableFee = models.DecimalField(default=self.set_fee(), max_digits=7, decimal_places=2)
    def set_fee(self):
        overridableFee =  2 * self.job.veryImportant

#gives...
#NameError: name 'self' is not defined

#3
from django.db import models

class Job(models.Model):
    veryImportant = models.IntegerField()
    def get_fee():
        return 2 * veryImportant

class Report(models.Model):
    job = models.ForeignKey(Job)
    overridableFee = models.DecimalField(max_digits=7, decimal_places=2)
    def __init__(self, *args, **kwargs):
        self.overridableFee = self.job.get_fee()
        super(models.Model, self).__init__(*args, **kwargs)

#gives...
#TypeError: object.__init__() takes no parameters

The error with #3 could be that I just have no idea how to override init properly. #3的错误可能是我不知道如何正确覆盖init I copied something out of another answer and gave up after it didn't work. 我从另一个答案中复制了一些东西,但在它没有用之后放弃了。

If none of these will work, I can always revert to just setting the fee after I create each Report in the view, but I'd rather do it automatically when the Report is created, for sanity. 如果这些都不起作用,我可以在视图中创建每个报告之后再回复设置费用,但我宁愿在创建报告时自动执行此操作,以获得理智。

EDIT: 编辑:

Ended up going with #3, fixed with Yuji's answer and modified to make sure any possible fee set from the shell overrides what job.get_fee() wants. 结束#3,修复Yuji的答案并修改以确保从shell中设置的任何可能的费用都会覆盖job.get_fee()想要的内容。

def __init__(self, *args, **kwargs):
    super(Report, self).__init__(*args, **kwargs)
    if self.overridableFee == None and self.job and not self.pk:
        self.overridableFee = self.job.get_fee()

Your last example could potentially work with some work: 您的最后一个示例可能适用于某些工作:

  1. First all, you need to __init__ on your class, not models.Model 首先,你需要在你的班级__init__ ,而不是models.Model
  2. You need to set your attribute after the model has been initialized 初始化模型 ,需要设置属性
  3. You need check if the model has been saved, or else your model will revert to the overridable fee every time you load it. 您需要检查模型是否已保存,否则每次加载模型时模型都将恢复为可覆盖的费用。

- -

class Job(models.Model):
    veryImportant = models.IntegerField()
    def get_fee():
        return 2 * veryImportant

class Report(models.Model):
    job = models.ForeignKey(Job)
    overridableFee = models.DecimalField(max_digits=7, decimal_places=2)
    def __init__(self, *args, **kwargs):
        super(Report, self).__init__(*args, **kwargs)
        if not self.id:
            self.overridableFee = self.job.get_fee() 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM