编辑:我完全重写了这个问题,因为原来的问题没有清楚地解释我的问题
我想运行一个特定于每个特定模型实例的函数。
理想情况下,我想要这样的事情:
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的子类,可能是这样的:
class MyModel(models.Model):
data = models.CharField(max_length=100)
perform_unique_action = default_function
class MyModelX(MyModel):
perform_unique_action = function_X
class MyModelY(MyModel):
perform_unique_action = function_Y
x = MyModelX(data='originalx')
x.perform_unique_action() #will do whatever is specified for instance x
y = MyModelY(data='originaly')
y.perform_unique_action() #will do whatever is specified for instance y
不幸的是,我认为我不能使用继承,因为我试图以这种方式访问函数:
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_action,我不知道外键在SecondModel中的类型。
我可以从SecondModel作为外键访问MyModel,并且仍然为MyModel的每个实例都有一个唯一的函数吗?
答案 0 :(得分:2)
这对我有用。我没有测试它,但你应该能够创建另一个类并覆盖他们的方法,它会工作。检查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!"
答案 1 :(得分:2)
我想出了两种为每个对象定义特定功能的方法。一个是使用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()
感谢所有回复的人,如果不是你的帮助,我无法得到这个答案。
答案 2 :(得分:0)
您可以执行一些覆盖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()
答案 3 :(得分:-1)
我不知道我是否理解你的正确与否。但是你可以查看这个例子here。
示例:
表示模型上属性的字符串。这与callable几乎相同,但在此上下文中self是模型实例。这是一个完整的模型示例:
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')