How to store functions in django models

爷,独闯天下 提交于 2019-12-06 04:28:53

This works for me. I haven't tested it, but you should be able to create another class and override their methods and it'll work. Check the class Meta line, it'll treat it as an abstract class. Here's an example of my actual classes that I'm working on right now.

EDIT: Added VoteComment class and tested it. It works as expected!

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!"

I came up with two ways of having a specific function defined for each object. One was using marshal to create bytecode which can be stored in the database (not a good way), and the other was by storing a reference to the function to be run, as suggested by Randall. Here is my solution using a stored reference:

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

Thanks to everyone who replied, I couldn't have got to this answer if it weren't for your help.

You could achive some similar behavior overriding the save method. And providing special callbacks to your instances.

Something like:

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

You can write endpoints on your server and limit their access to just your self. Then store in each model instance corresponding url. For example:

views.py

def funx_x(request):
    pass

def func_y(request):
    pass

models.py:

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

and then:

x = MyModel(data='originalx', perform_unique_action='http://localhost/funx_x')
requests.post(x.perform_unique_action)

i dont know whether i understand u correct or not. but you can check out this example here.

Example:

A string representing an attribute on the model. This behaves almost the same as the callable, but self in this context is the model instance. Here's a full model example:

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')
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!