如何在Django模型中存储函数

2024-09-29 05:21:23 发布

您现在位置:Python中文网/ 问答频道 /正文

编辑:我完全重写了这个问题,因为原来的问题没有清楚地解释我的问题

我想运行一个特定于每个特定模型实例的函数。在

理想情况下,我想要这样的东西:

class MyModel(models.Model):
    data = models.CharField(max_length=100)
    perform_unique_action = models.FunctionField() #stores a function specific to this instance

x = MyModel(data='originalx', perform_unique_action=func_for_x)
x.perform_unique_action() #will do whatever is specified for instance x

y = MyModel(data='originaly', perform_unique_action=func_for_y)
y.perform_unique_action() #will do whatever is specified for instance y

但是没有数据类型FunctionField。通常,这可以通过继承和创建MyModel的子类来解决,可能如下所示:

^{pr2}$

不幸的是,我不认为我可以使用继承,因为我试图通过以下方式访问函数:

class MyModel(models.Model):
    data = models.CharField(max_length=100)
    perform_unique_action = default_function

class SecondModel(models.Model):
    other_data = models.IntegerField()
    mymodel = models.ForeignKey(MyModel)

secondmodel = SecondModel.objects.get(other_data=3)
secondmodel.mymodel.perform_unique_action()

问题似乎是,如果我重写子类中的perform_unique_操作,我不知道SecondModel中的外键将是什么类型。在

我可以从SecondModel作为外键访问MyModel,并且仍然对MyModel的每个实例有一个唯一的函数吗?在


Tags: 实例instance函数fordatamodelmodelsaction
3条回答

这对我有用。我还没有测试过它,但是你应该能够创建另一个类并重写它们的方法,这样就可以工作了。检查class Meta行,它将把它当作一个抽象类。这里有一个我正在学习的实际类的例子。在

编辑:添加了VoteComment类并对其进行了测试。一切如期而至!在

class Vote(models.Model):
    VOTE_ENUM = (
        (VoteEnum.DOWN_VOTE, VoteEnum.toString(VoteEnum.DOWN_VOTE)),
        (VoteEnum.NONE, VoteEnum.toString(VoteEnum.NONE)),
        (VoteEnum.UP_VOTE, VoteEnum.toString(VoteEnum.UP_VOTE)),

    )
    question = models.ForeignKey(Question, null=False, editable=False, blank=False)
    voter = models.ForeignKey(User, blank=False, null=False, editable=False)
    vote_type = models.SmallIntegerField(default=0, null=False, blank=False, choices=VOTE_ENUM)

    class Meta:
        abstract = True

    def is_upvote(self):
        return self.vote_type > 0
    def is_downvote(self):
        return self.vote_type < 0

class VoteAnswer(Vote):
    answer = models.ForeignKey(Answer, null=False, editable=False, blank=False)

    class Meta:
        unique_together = (("voter", "answer"),) # to prevent user from voting on the same question/answer/comment again

    def __unicode__(self):
        vote_type = "UP" if vote_type > 0 else ("DOWN" if vote_type < 0 else "NONE")
        return u"{0}: [{1}] {2}".format(user.username, vote_type, answer.text[:32])

    def is_upvote(self):
        return "FOO! "+str(super(VoteAnswer, self).is_upvote())

class VoteComment(Vote):
    comment = models.ForeignKey(Comment, null=False, editable=False, blank=False)

    class Meta:
        unique_together = (("voter", "comment"),) # to prevent user from voting on the same question/answer/comment again

    def __unicode__(self):
        vote_type = "UP" if vote_type > 0 else ("DOWN" if vote_type < 0 else "NONE")
        return u"{0}: [{1}] {2}".format(user.username, vote_type, comment.text[:32])

    def is_upvote(self):
        return "BAR!"

我想出了两种为每个对象定义特定函数的方法。一种是使用marshal创建可以存储在数据库中的字节码(不是一种好方法),另一种方法是根据Randall的建议,存储对要运行的函数的引用。以下是我使用存储引用的解决方案:

class MyModel(models.Model):
    data = models.CharField(max_length=100)
    action_module = models.CharField(max_length=100)
    action_function = models.CharField(max_length=100)

class SecondModel(models.Model):
    other_data = models.IntegerField()
    mymodel = models.ForeignKey(MyModel)

secondmodel_obj = SecondModel.objects.get(other_data=3)
#The goal is to run a function specific to the instance
#of MyModel referred to in secondmodel_obj

module_name = secondmodel_obj.mymodel.action_module
func_name = secondmodel_obj.mymodel.action_function

module = __import__(module_name)
func = vars(module)[func_name]
func()

感谢所有回复我的人,如果不是你的帮助,我不可能得到这个答案。在

您可以实现重写save方法的类似行为。并提供对实例的特殊回调。在

比如:

def default_function(instance):
    #do something with the model instance

class ParentModel(model.Model):
    data = models.CharField()
    callback_function = default_function

    def save(self, *args, **kwargs):
        if hasattr(self, 'callback_function'):
            self.callback_function(self)
        super(ParentModel, self).save(*args, **kwargs)

class ChildModel():
    different_data = models.CharField()
    callback_function = other_fun_specific_to_this_model

instance = ChildModel()
#Specific function to this particular instance
instance.callback_function = lambda inst: print inst.different_data
instance.save()

相关问题 更多 >