【问题标题】:Simple multiplication in model's attribute django?模型属性django中的简单乘法?
【发布时间】:2012-05-25 07:34:49
【问题描述】:

我试图在这段代码中为属性阈值设置一个默认值,阈值应该是当前级别*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'

【问题讨论】:

    标签: python django


    【解决方案1】:

    最好是在保存对象的同时进行这样的计算。所以覆盖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)
    

    我在带有测试用例的 bitbucket 上创建了一个小型 django 项目djangodepends

    【讨论】:

    • 我按照您的建议尝试了覆盖方法,但是当我需要从管理员访问这些级别但无法更改阈值时,以及当我覆盖保存并尝试创建新级别时阈值是空的,请注意我现在删除了 editable=False 来检查
    • @FadyKamal 尝试了我的依赖字段方法,可以轻松检查是否正在添加模型,因此它将仅为新模型设置默认值,尽管 Model.save 覆盖也应该有效
    • 成功了!!很好,唯一的问题是我在管理视图中看不到它,但它可以工作,非常感谢!!
    【解决方案2】:

    您可以覆盖保存方法来计算。

    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.
    

    【讨论】:

    • 我尝试了您的方法,但是当我需要从管理员访问这些级别但无法更改阈值时,当我覆盖保存并尝试创建新级别时,阈值为空,注意我现在删除了 editable=False 来检查
    猜你喜欢
    • 2014-03-30
    • 2017-08-05
    • 2011-10-31
    • 1970-01-01
    • 2018-01-18
    • 2017-05-04
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多