2

編集:元の質問が私の質問を明確に説明していなかったので、私は質問を完全に書き直しました

特定のモデルインスタンスごとに固有の関数を実行したいと思います。

理想的には、次のようなものが必要です。

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のインスタンスごとに一意の関数を使用できますか?

4

5 に答える 5

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!"
于 2012-06-21T03:22:15.883 に答える
2

オブジェクトごとに特定の関数を定義する2つの方法を思いつきました。1つは、マーシャルを使用してデータベースに格納できるバイトコードを作成することでした(良い方法ではありません)。もう1つは、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()

返信してくれた皆さんのおかげで、あなたの助けがなければ、私はこの答えにたどり着くことができなかったでしょう。

于 2012-06-21T10:27:05.337 に答える
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()
于 2012-06-20T14:12:39.667 に答える
0

サーバーにエンドポイントを記述し、それらのアクセスを自分だけに制限することができます。次に、各モデルインスタンスに対応するURLを保存します。例えば:

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

その後:

x = MyModel(data='originalx', perform_unique_action='http://localhost/funx_x')
requests.post(x.perform_unique_action)
于 2018-09-12T08:16:07.397 に答える
-1

私はあなたが正しいかどうかを理解しているかどうかわかりません。ただし、この例はここで確認できます。

例:

モデルの属性を表す文字列。これは呼び出し可能オブジェクトとほぼ同じように動作しますが、このコンテキストでの自己はモデルインスタンスです。完全なモデルの例を次に示します。

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')
于 2012-06-20T14:38:00.577 に答える