1

このコードで属性しきい値のデフォルト値を設定しようとしています。しきい値は現在のレベル * 50 である必要があり、これがモデルです

class Level (models.Model):
    name = models.CharField(max_length=20,null=True, blank=True)
    description = models.CharField(max_length=20, null=True, blank=True)
    number = models.IntegerField(null=True, blank=True)
    threshold = models.IntegerField(null=True, blank=True,default=50*number,editable=False)

エラーが発生しますunsupported operand types for * : 'int' and 'IntegerField'

4

2 に答える 2

2

オブジェクトを保存するときにそのような計算を行うのが最善です。だからオーバーライドModel.save

または、より一般的な方法は、カスタム フィールドを記述してpre_saveをオーバーライドすることです。

class DependentIntegerField(models.IntegerField):

    def pre_save(self, model_instance, add):
        if not add: # set the default only while adding model
            return super(self, DependentIntegerField).pre_save(model_instance, add)

        return model_instance.number*50

それをさらに拡張してDependentIntegerFieldジェネリックにすることで、callable を渡して任意の計算を行うことができます。また、デフォルト値を使用する前にユーザーが値を設定したかどうかをチェックするなどのさらなる拡張を行うことができ、よりジェネリックにすることができます。フィールドクラスをファクトリ関数に渡すことにより、任意のフィールドを依存フィールドとして作成できます。例えば

from django.db import models

class_map = {}

def depends_field_pre_save(self, model_instance, add):
    """
    if default is not callable or it is not a model add, lets skip our hook
    """
    if not add or not callable(self.default):
        super(self.__class__, self).__init__(self,*args, **kwargs)
    value = self.default(model_instance)
    setattr(model_instance, self.attname, value)
    return value

def FieldDepends(field_class):
    """
    return a dervied class from field_class which supports dependent default
    """
    if field_class in class_map:
        # we already created this class so return that
        return class_map[field_class]

    new_class = type('Depends'+field_class.__name__, (field_class,), {'pre_save':depends_field_pre_save })

    class_map[field_class] = new_class

    return new_class

そして、このように使用します

class DependentModel(models.Model):

    def threshold_default(model_instance=None):
        if model_instance is None:
            return 10
        return model_instance.number*10

    number = models.IntegerField(null=True, blank=True, default=10)
    threshold = FieldDepends(models.IntegerField)(null=True, blank=True, default=threshold_default,editable=False)

小さな django プロジェクトdjangodepends on bitbucket with test cases を作成しました

于 2012-05-17T17:35:02.980 に答える
1

保存方法を計算にオーバーライドできます。

https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

class Level (models.Model):
    name = models.CharField(max_length=20,null=True, blank=True)
    description = models.CharField(max_length=20, null=True, blank=True)
    number = models.IntegerField(null=True, blank=True)
    threshold = models.IntegerField(null=True, blank=True ,editable=False)

    def save(self, *args, **kwargs):
        try:
          self.threshold = self.number * 50
        except TypeError:
          pass
        super(Level, self).save(*args, **kwargs) # Call the "real" save() method.
于 2012-05-17T17:35:20.947 に答える