Может ли значение поля модели Django по умолчанию быть определено функцией, зависящей от внешней родительской модели? - PullRequest
7 голосов
/ 25 октября 2011

Я пытаюсь, чтобы значение по умолчанию Report было основано на атрибутах родительской модели. Я не хочу делать это в save(), потому что поле должно быть представлено пользователю, если он решит переопределить значение перед сохранением.

Вот три метода, которые я пробовал, помимо передачи только указателей на функции (т. Е. Без ()). Ошибки возникают, когда я запускаю 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

Ошибка с # 3 может заключаться в том, что я просто не знаю, как правильно переопределить init . Я скопировал что-то из другого ответа и сдался после того, как это не сработало.

Если ни один из них не сработает, я всегда могу вернуться к установлению платы после создания каждого отчета в представлении, но я бы предпочел сделать это автоматически при создании отчета, для здравого смысла.

EDIT:

Завершено переходом к # 3, исправлено ответом Юджи и изменено, чтобы гарантировать, что любая возможная плата, установленная из оболочки, переопределяет то, что требуется 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()

1 Ответ

7 голосов
/ 25 октября 2011

Ваш последний пример может потенциально работать с некоторой работой:

  1. Прежде всего, вам нужно __init__ в вашем классе, а не models.Model
  2. Вам необходимо установитьатрибут после модель была инициализирована
  3. Вам необходимо проверить, была ли модель сохранена, иначе ваша модель будет возвращаться к платной плате каждый раз, когда вы ее загружаете.

-

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